gpt4 book ai didi

java - 自定义绘画和 Z 顺序 : query re painting order

转载 作者:行者123 更新时间:2023-12-02 09:09:39 24 4
gpt4 key购买 nike

所以,我想对 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 索引相对应。(例如,索引 1 处的组件应在索引 0 的组件之上渲染)

但是,当渲染器 (JPanel) 添加到窗口 (JFrame) 并调用 paintComponent 时,不会发生任何情况。从字面上看,没有任何绘画。

注释掉主类中的 Z 顺序代码使得至少有一些东西实际上可以绘制,但是红色绘制在蓝色之上(因为在 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% 面向组件,而不是两者兼而有之

Why do the components display in the order that they are called within the PaintComponent, and not displayed in the order that they are set to within the JFrame?

因为你不负责绘制组件并且你正在搞乱系统

组件/ZOrder 示例

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

public static void main(String[] args) {
new Test();
}

public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

private JPanel blueBox;
private JPanel redBox;

private JPanel top, bottom;

public TestPane() {
blueBox = makeBox(Color.BLUE);
redBox = makeBox(Color.RED);

setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
// Filler
add(emptyBox(), gbc);

gbc.gridwidth = 2;
gbc.gridheight = 2;
gbc.fill = GridBagConstraints.BOTH;
add(blueBox, gbc);

gbc.gridx++;
gbc.gridy++;
add(redBox, gbc);

// Filler
gbc.gridx++;
gbc.gridy++;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.NONE;
add(emptyBox(), gbc);

JButton flip = new JButton("Flip");
flip.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setComponentZOrder(bottom, 0);
JPanel temp = top;
top = bottom;
bottom = temp;
repaint();
}
});

gbc.gridx = 0;
gbc.gridy = 4;
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(flip, gbc);

top = blueBox;
bottom = redBox;
}

protected JPanel emptyBox() {
JPanel box = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
};
box.setOpaque(false);
return box;
}

protected JPanel makeBox(Color color) {
JPanel box = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
};
box.setBackground(color);
return box;
}

}

}

自定义绘画

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

public static void main(String[] args) {
new Test();
}

public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

private List<Box> boxes = new ArrayList<Box>(2);

public TestPane() {
boxes.add(new Box(Color.BLUE, 0, 0));
boxes.add(new Box(Color.RED, 50, 50));

setLayout(new BorderLayout());

JButton flip = new JButton("Flip");
flip.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// Ok, this is a cheat as I only have to boxes,
// if you had more, you'd need to move the box you
// higher in the rendering order closer to the end
// of the list
Collections.reverse(boxes);
repaint();
}
});
add(flip, BorderLayout.SOUTH);
}

@Override
public Dimension getPreferredSize() {
return new Dimension(150, 150);
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);

// Cheat, I should looping over the box array to calculate the
// area the boxes actuall occupy
int x = (getWidth() - 150) / 2;
int y = (getHeight() - 150) / 2;

Graphics2D g2d = (Graphics2D) g.create();
g2d.translate(x, y);

for (Box box : boxes) {
box.paint(g2d);
x += 50;
y += 50;
}
g2d.dispose();
}
}

public class Box {

private Color color;

private int x, y;

public Box(Color color, int x, int y) {
this.color = color;
this.x = x;
this.y = y;
}

public void paint(Graphics2D g2d) {
g2d.setColor(color);
g2d.fillRect(x, y, 100, 100);
}
}

}

关于java - 自定义绘画和 Z 顺序 : query re painting order,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59525296/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com