Java 如何在画布上画画?
我希望在3D OpenGL视图上绘制某种HUD,但似乎在我的面板中绘制的任何图形都会被忽略,尽管已经完成了 这里有一些简单的代码 我的框架Java 如何在画布上画画?,java,swing,opengl,jpanel,awt,Java,Swing,Opengl,Jpanel,Awt,我希望在3D OpenGL视图上绘制某种HUD,但似乎在我的面板中绘制的任何图形都会被忽略,尽管已经完成了 这里有一些简单的代码 我的框架 public class MyFrame extends JFrame{ private static final long serialVersionUID = 1L; public MyFrame(Labyrinth l){ super(); this.setTitle("My Frame");
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(图形)、paintComponent(图形)和update()。有人说,在“重量级”组件上绘制是复杂的,我应该直接在组件中绘制,或者使用另一种类型。我显然需要GLCanvas来显示3D渲染,同时它似乎没有提供绘制覆盖的工具。有人告诉我只需在JFrame的玻璃窗格中画画,但这似乎有点过分,而且我被告知永远不要在玻璃窗格中玩耍,所以我不打算这样做
我看过很多关于绘画调用顺序的主题,但我无法确定在重写某个或某个方法时哪个是正确的,我甚至不知道是否应该重写,或者应该重写哪个方法。有没有一种明显的方式我会错过在GLCanvas组件上展示我的简单JPanel绘画?首先,我真的不建议通过这种方式获得HUD。因为我只能想象这种令人痛苦的表演。当然,我从未尝试过像那样混合Java、OpenGL和AWT的图形
现在不要使用管道带来保存这些类,考虑使用<代码> JLAIERDEPANE < /C> > < /P>
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);
否则,您将遇到与以前相同的问题:
绘画发生了,但没有显示在视图中
为了演示它的工作原理,我创建了一个类似于您的MyPanel
的小型TestPanel
类
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面板的大小调整将为您处理。请注意,必须在GLJPanel
组件中绘制三维图形,否则分层将不起作用(与不是Swing组件的GLCanvas相反)。调用paintComponent(图形g)
的速率将与GLJPanel的帧速率相同。另外请注意,玻璃窗格在默认情况下是隐藏的,因此必须对其调用setVisible(true)
import javax.swing.JFrame;
导入com.jogamp.opengl.awt.GLJPanel;
// ...
公共类应用程序窗口扩展JFrame{
公共应用程序窗口(字符串标题){
超级(标题);
GLCapabilities gl_profile=新的GLCapabilities(GLProfile.getDefault());
GLJPanel gl_canvas=新的GLJPanel(gl_配置文件);
//…在此处编写代码以绘制图形(为gl_画布提供一个GLEventListener)
setContentPane(gl_画布);
StatusTextOverlyPanel myGlassPane=新的StatusTextOverlyPanel();
setGlassPane(myGlassPane);
myGlassPane.setVisible(true);
setVisible(真);
}
类StatusTextOverlyPanel扩展JComponent{
@凌驾
公共组件(图形g){
超级组件(g);
Graphics2D g2d=(Graphics2D)g;
g2d.setFont(新字体(Font.MONOSPACED,Font.PLAIN,14));
g2d.setPaint(颜色:黑色);
String statusText=String.format(“C-elev:%.2f S-view%.2f D-view%.2f”,1459.0,17.0,2.574691);
g2d.抽绳(statusText,10,20);
}
}
}
下面是一个它可能看起来像什么的示例(您需要额外的代码来绘制所示的轴和正方形)
是否可以沿分层窗格调整子面板的大小?我想当尺寸变化时,重写LP的repaint方法为它的组件设置标志是可行的。不管怎样,这就是我想要的,谢谢你。不过我还有一个问题要问你,这不会成为另一个话题;我怎样才能看穿顶部JPanel的非涂漆部分?现在,当我试图在画布上只绘制面板左上角的四分之一时,我得到了类似的结果。这很好,但还不够。(编辑:使用setOpaque(false);在面板实例上)调整大小可以使用
ComponentListener
并在componentResized
中调整子面板的大小。对于透明度问题,如果您覆盖了paintComponent
,并且没有调用super.paintComponent
,并且没有用颜色清除面板,那么这个问题就不应该存在了。我已经覆盖了所有形式的paint方法,包括使用和不使用super调用,但都没有效果。我已经切换到GLJPanel而不是GLCanvas,它立即起作用了,尽管我不知道为什么我不想质疑它。componentListener thingy可以工作,但会有延迟(组件大小错误的窗口的闪烁),因为在调整大小时,绘制是在处理事件之前完成的,我只需像往常一样,在检测到调整大小时设置自己的标志。谢谢你的回答。同样重要的是要注意,我的截图中显示的灰色默认背景色来自包含画布的面板,而不是我绘制的那个。改变画布面板的背景也改变了它;我画的面板确实是透明的,但是下面的面板无法更新画布上完全隐藏在透明面板后面的部分。