【发布时间】:2020-04-18 20:56:57
【问题描述】:
所以,我想对JFrame 中的一些组件进行 Z 排序。
组件:
public class aBLUEBox extends JPanel{
int xPos = 19;
int yPos = 20;
int width = 10;
int height = 80;
public void paintBox(Graphics g){
g.setColor(Color.BLUE);
g.fillRect(xPos,yPos,width,height);
}
}
框架:
public class CreateWindow extends JFrame{
CreateWindow(){
this.setTitle("Layering Test");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(1920/2,1080/2);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setVisible(true);
}
}
将组件添加到框架/主类中:
public class LayerMain {
CreateWindow window;
static aBLUEBox BLUEBox;
static aREDBox REDBox; //A Different Component just like aBLUEBox, but with an altered PaintBox() method which paints a red box instead of a blue one.
PanelRenderer RendererP;
LayerMain(){
BLUEBox = new aBLUEBox();
REDBox = new aREDBox();
RendererP = new PanelRenderer(); //holds the PaintComponent Method. Class for this is shown below.
window = new CreateWindow();
window.add(BLUEBox);
window.add(REDBox);
window.setComponentZOrder(BLUEBox, 0);
window.setComponentZOrder(REDBox, 0); //puts red on 0, moving blue up to 1.
//So now, BLUEBox's Z-order is 1, thus BLUEBox is on top of REDBox.
System.out.println("Z-order of blue = " + window.getComponentZOrder(BLUEBox)); //Prints 1
System.out.println("Z-order of Red = " + window.getComponentZOrder(REDBox)); //Prints 0
window.add(RendererP);
RendererP.repaint(); //Should Paint both box's.
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new LayerMain();
}
});
}
}
然后,我想使用 repaint() 调用来渲染这些组件。
渲染器:
public class PanelRenderer extends JPanel{
public void paintComponent(Graphics g){
super.paintComponent(g);
//JPanels:
LayerMain.BLUEBox.paintBox(g); //Paints Blue first, not that it should matter.
LayerMain.REDBox.paintBox(g); //Paints Red Second, not that it should matter.
System.out.println("PaintComponent invoked.");
}
}
应该在顶部/下方呈现的内容应该对应于框架中组件的 Z-index。 (例如,索引 1 处的组件应在组件顶部呈现索引 0)
但是,当将渲染器 (JPanel) 添加到窗口 (JFrame) 并调用 paintComponent 时,什么都不会发生。从字面上看,没有任何油漆。
注释掉主类中的 Z-order 代码使得至少有一些东西实际上是在绘制,但是红色绘制在蓝色之上(因为在 PaintComponent 方法中,红色最后绘制,因此在顶部),这不是我想要的。
//window.setComponentZOrder(BLUEBox, 0);
//window.setComponentZOrder(REDBox, 0); //puts red on 0, moving blue up to 1.
为什么组件在paintComponent 中按调用顺序显示,而不按在JFrame 中设置的顺序显示?
MRE / SSCCE
import java.awt.*;
import javax.swing.*;
public class LayerMain {
CreateWindow window;
static ColoredBox blueBox;
//A Different Component just like aBLUEBox, but with an altered
// PaintBox() method which paints a red box instead of a blue one.
static ColoredBox redBox;
PanelRenderer rendererP;
LayerMain(){
blueBox = new ColoredBox(Color.BLUE);
redBox = new ColoredBox(Color.RED);
//holds the PaintComponent Method. Class for this is shown below.
rendererP = new PanelRenderer();
window = new CreateWindow();
window.add(blueBox);
window.add(redBox);
window.setComponentZOrder(blueBox, 0);
window.setComponentZOrder(redBox, 0); //puts red on 0, moving blue up to 1.
//So now, blueBox's Z-order is 1, thus blueBox is on top of redBox.
System.out.println("Z-order of blue = " + window.getComponentZOrder(blueBox)); //Prints 1
System.out.println("Z-order of Red = " + window.getComponentZOrder(redBox)); //Prints 0
window.add(rendererP);
rendererP.repaint(); //Should Paint both box's.
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new LayerMain();
});
}
}
class PanelRenderer extends JPanel{
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
//JPanels:
LayerMain.blueBox.paintBox(g); //Paints Blue first, not that it should matter.
LayerMain.redBox.paintBox(g); //Paints Red Second, not that it should matter.
System.out.println("PaintComponent invoked.");
}
}
class CreateWindow extends JFrame{
CreateWindow(){
this.setTitle("Layering Test");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(1920/2,1080/2);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setVisible(true);
}
}
class ColoredBox extends JPanel {
int xPos = 19;
int yPos = 20;
int width = 10;
int height = 80;
Color color;
ColoredBox(Color color) {
super();
this.color = color;
}
public void paintBox(Graphics g){
g.setColor(color);
g.fillRect(xPos,yPos,width,height);
}
}
【问题讨论】:
-
好的,不。这绝对不是您应该尝试执行自定义绘画或使用自定义组件的方式。你不负责组件的渲染,所以你的
PanelRenderer没有意义,你不应该真的这样使用static,它只是懒惰而且容易出错。要么让它 100% 定制绘画,要么 100% 面向组件,而不是两者 -
问题底部附近标记为 MRE / SSCCE 的编辑是否显示原始代码中的问题?
-
@AndrewThompson 是的。
标签: java swing paintcomponent z-order custom-painting