如何绘制 GLCanvas?
How to draw over a GLCanvas?
我希望在 3D OpenGL 视图上绘制某种 HUD,但似乎在我的面板中完成的任何绘制都将被忽略,尽管已完成。
这是一些准系统代码。
我的框架;
public class MyFrame extends JFrame{
private static final long serialVersionUID = 1L;
public MyFrame(Labyrinth l){
super();
this.setTitle("My Frame");
this.setSize(512, 384);
this.setContentPane(new MyPanel());
//this.setVisible(true);//If needed here.
}
}
我的面板;
public class MyPanel extends JPanel {
private static final long serialVersionUID = 1L;
public MyPanel(){
super();
this.setLayout(new BorderLayout());
MyCanvas mc=new MyCanvas(l);
mc.setFocusable(false);
this.add(this.mc, BorderLayout.CENTER);
//this.revalidate();//Doesn't seem needed in the instanciation.
}
public void paintComponent(Graphics g){
super.paintComponent(g);
this.mc.repaint();
g.setColor(new Color(128,128,128));
g.fillRect(0, 0, this.getWidth()/2,this.getHeight()/2);
//top-left quarter should be greyed away.
}
}
我的画布;
public class MyCanvas extends GLCanvas{
private static final long serialVersionUID = 1L;
public MyCanvas(){
super(new GLCapabilities(GLProfile.getDefault()));
}
}
绘画发生了,但没有显示在视图中。我试过重写 repaint()、paint(Graphics)、paintComponent(Graphics) 和 update()。有人说在 "heavyweight" 组件上绘制很复杂,我应该直接在组件上绘制或使用其他类型。我显然需要 GLCanvas 来显示 3D 渲染,同时它似乎没有提供绘制叠加层的工具。有人告诉我只需在 JFrame 的 glassPane 中进行绘图,但这似乎太过分了,而且我被告知永远不要在 glassPane 周围玩耍,所以我不打算那样做。
我看过很多关于绘画调用顺序的话题,但是我无法确定在覆盖这样或那样的方法时哪个是正确的,我什至不知道我是否应该覆盖或应该覆盖哪种方法。有没有一种明显的方法让我错过了在其 GLCanvas 组件上显示我的简单 JPanel 绘画?
首先,我真的不建议通过这些方式获得 HUD。因为我只能想象这种伤害表现很多。当然,我从未尝试过像那样混合 Java、OpenGL 和 AWT 的图形。
现在不要使用 用胶带 将那些 class 固定在一起,而是考虑使用 JLayeredPane
。
JLayeredPane layeredPane = new JLayeredPane();
layeredPane.add(new MyCanvas());
layeredPane.add(new MyPanel());
frame.add(layeredPane);
现在重要的部分是您必须手动设置两个组件的边界:
canvas.setBounds(x, y, width, height);
panel.setBounds(x, y, width, height);
否则你会遇到和以前一样的问题:
The painting takes place, but isn't shown in the view
为了演示它的工作原理,我创建了这个与您的 MyPanel
.
相似的小 TestPanel
class
public static class TestPanel extends JPanel {
private Color color;
public TestPanel(Color color) {
this.color = color;
}
@Override
public void paintComponent(Graphics g) {
g.setColor(color);
g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
}
}
然后像这样创建两个实例:
JPanel panel1 = new TestPanel(new Color(255, 0, 0));
panel1.setBounds(25, 25, 100, 100);
JPanel panel2 = new TestPanel(new Color(0, 0, 255));
panel2.setBounds(75, 75, 100, 100);
然后将它们添加到 JLayeredPane
并将其添加到 JFrame
,我们看到:
我发现使用 JFrame
玻璃面板是一个很好的解决方案,我用它在 3D 图形上绘制调试文本,我没有遇到任何问题。使用玻璃面板方法比使用 JLayeredPane
更方便,因为 3D 面板的大小调整将为您处理。请注意,3D 图形必须在 GLJPanel
组件中绘制,否则分层将不起作用(与不是 Swing 组件的 GLCanvas 相反)。 paintComponent(Graphics g)
将以与 GLJPanel 的帧速率相同的速率调用。另请注意,默认情况下玻璃窗格是隐藏的,因此必须在其上调用 setVisible(true)
。
import javax.swing.JFrame;
import com.jogamp.opengl.awt.GLJPanel;
// ...
public class ApplicationWindow extends JFrame {
public ApplicationWindow(String title) {
super(title);
GLCapabilities gl_profile = new GLCapabilities(GLProfile.getDefault());
GLJPanel gl_canvas = new GLJPanel(gl_profile);
// ... code here to draw the graphics (supply a GLEventListener to gl_canvas)
setContentPane(gl_canvas);
StatusTextOverlayPanel myGlassPane = new StatusTextOverlayPanel();
setGlassPane(myGlassPane);
myGlassPane.setVisible(true);
setVisible(true);
}
class StatusTextOverlayPanel extends JComponent {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 14));
g2d.setPaint(Color.BLACK);
String statusText = String.format("C-elev: %.2f S-view %.2f D-view %.2f", 1459.0, 17.0, 2.574691);
g2d.drawString(statusText, 10, 20);
}
}
}
这是它的外观示例(您需要额外的代码来绘制轴和显示的正方形)
我希望在 3D OpenGL 视图上绘制某种 HUD,但似乎在我的面板中完成的任何绘制都将被忽略,尽管已完成。
这是一些准系统代码。
我的框架;
public class MyFrame extends JFrame{
private static final long serialVersionUID = 1L;
public MyFrame(Labyrinth l){
super();
this.setTitle("My Frame");
this.setSize(512, 384);
this.setContentPane(new MyPanel());
//this.setVisible(true);//If needed here.
}
}
我的面板;
public class MyPanel extends JPanel {
private static final long serialVersionUID = 1L;
public MyPanel(){
super();
this.setLayout(new BorderLayout());
MyCanvas mc=new MyCanvas(l);
mc.setFocusable(false);
this.add(this.mc, BorderLayout.CENTER);
//this.revalidate();//Doesn't seem needed in the instanciation.
}
public void paintComponent(Graphics g){
super.paintComponent(g);
this.mc.repaint();
g.setColor(new Color(128,128,128));
g.fillRect(0, 0, this.getWidth()/2,this.getHeight()/2);
//top-left quarter should be greyed away.
}
}
我的画布;
public class MyCanvas extends GLCanvas{
private static final long serialVersionUID = 1L;
public MyCanvas(){
super(new GLCapabilities(GLProfile.getDefault()));
}
}
绘画发生了,但没有显示在视图中。我试过重写 repaint()、paint(Graphics)、paintComponent(Graphics) 和 update()。有人说在 "heavyweight" 组件上绘制很复杂,我应该直接在组件上绘制或使用其他类型。我显然需要 GLCanvas 来显示 3D 渲染,同时它似乎没有提供绘制叠加层的工具。有人告诉我只需在 JFrame 的 glassPane 中进行绘图,但这似乎太过分了,而且我被告知永远不要在 glassPane 周围玩耍,所以我不打算那样做。
我看过很多关于绘画调用顺序的话题,但是我无法确定在覆盖这样或那样的方法时哪个是正确的,我什至不知道我是否应该覆盖或应该覆盖哪种方法。有没有一种明显的方法让我错过了在其 GLCanvas 组件上显示我的简单 JPanel 绘画?
首先,我真的不建议通过这些方式获得 HUD。因为我只能想象这种伤害表现很多。当然,我从未尝试过像那样混合 Java、OpenGL 和 AWT 的图形。
现在不要使用 用胶带 将那些 class 固定在一起,而是考虑使用 JLayeredPane
。
JLayeredPane layeredPane = new JLayeredPane();
layeredPane.add(new MyCanvas());
layeredPane.add(new MyPanel());
frame.add(layeredPane);
现在重要的部分是您必须手动设置两个组件的边界:
canvas.setBounds(x, y, width, height);
panel.setBounds(x, y, width, height);
否则你会遇到和以前一样的问题:
The painting takes place, but isn't shown in the view
为了演示它的工作原理,我创建了这个与您的 MyPanel
.
TestPanel
class
public static class TestPanel extends JPanel {
private Color color;
public TestPanel(Color color) {
this.color = color;
}
@Override
public void paintComponent(Graphics g) {
g.setColor(color);
g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
}
}
然后像这样创建两个实例:
JPanel panel1 = new TestPanel(new Color(255, 0, 0));
panel1.setBounds(25, 25, 100, 100);
JPanel panel2 = new TestPanel(new Color(0, 0, 255));
panel2.setBounds(75, 75, 100, 100);
然后将它们添加到 JLayeredPane
并将其添加到 JFrame
,我们看到:
我发现使用 JFrame
玻璃面板是一个很好的解决方案,我用它在 3D 图形上绘制调试文本,我没有遇到任何问题。使用玻璃面板方法比使用 JLayeredPane
更方便,因为 3D 面板的大小调整将为您处理。请注意,3D 图形必须在 GLJPanel
组件中绘制,否则分层将不起作用(与不是 Swing 组件的 GLCanvas 相反)。 paintComponent(Graphics g)
将以与 GLJPanel 的帧速率相同的速率调用。另请注意,默认情况下玻璃窗格是隐藏的,因此必须在其上调用 setVisible(true)
。
import javax.swing.JFrame;
import com.jogamp.opengl.awt.GLJPanel;
// ...
public class ApplicationWindow extends JFrame {
public ApplicationWindow(String title) {
super(title);
GLCapabilities gl_profile = new GLCapabilities(GLProfile.getDefault());
GLJPanel gl_canvas = new GLJPanel(gl_profile);
// ... code here to draw the graphics (supply a GLEventListener to gl_canvas)
setContentPane(gl_canvas);
StatusTextOverlayPanel myGlassPane = new StatusTextOverlayPanel();
setGlassPane(myGlassPane);
myGlassPane.setVisible(true);
setVisible(true);
}
class StatusTextOverlayPanel extends JComponent {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 14));
g2d.setPaint(Color.BLACK);
String statusText = String.format("C-elev: %.2f S-view %.2f D-view %.2f", 1459.0, 17.0, 2.574691);
g2d.drawString(statusText, 10, 20);
}
}
}
这是它的外观示例(您需要额外的代码来绘制轴和显示的正方形)