我試圖讓多個JPanels 可以“重疊”,也允許我執行自定義繪畫。
為此,我使用了 a MainPanel,它 extends JLayeredPane,據我所見,我已經正確設定了邊界和索引。
預期的結果是兩個矩形同時繪制到螢屏上。
我得到的結果是在兩個OverlappingPanels 中的一個上閃爍,我認為這是從RepaintManager要繪制的面板上進行的戰斗(在此處找到)。
我的問題是,如何使用 Swing 正確重疊面板并保留繪畫能力?
編輯:
有問題的代碼:
import javax.swing.*;
import java.awt.*;
public class Example extends JFrame {
public static class MainPanel extends JLayeredPane implements Runnable {
public OverlappingPanel1 overlappingPanel1;
public OverlappingPanel2 overlappingPanel2;
Thread mainThread;
public void startMainThread() {
mainThread = new Thread(this);
mainThread.start();
}
public MainPanel() {
this.setPreferredSize(new Dimension(1920,720));
this.setBackground(Color.BLACK);
this.setDoubleBuffered(true);
overlappingPanel1 = new OverlappingPanel1();
overlappingPanel2 = new OverlappingPanel2();
overlappingPanel1.setBounds(0,0,1920,720);
overlappingPanel2.setBounds(0,720/2,1920,720);
add(overlappingPanel1,1);
add(overlappingPanel2,2);
}
@Override
public void run() {
while(mainThread != null) {
overlappingPanel1.repaint();
overlappingPanel2.repaint();
}
}
}
public static class OverlappingPanel1 extends JPanel {
public OverlappingPanel1() {
setDoubleBuffered(true);
setPreferredSize(new Dimension(1920,720));
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D graphics2D = (Graphics2D) g;
graphics2D.fillRect(0,0,200,200);
}
}
public static class OverlappingPanel2 extends JPanel {
public OverlappingPanel2() {
setDoubleBuffered(true);
setPreferredSize(new Dimension(1920,720));
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D graphics2D = (Graphics2D) g;
graphics2D.fillRect(0,80,200,200);
}
}
public static void main(String[] args) {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(false);
MainPanel mainPanel = new MainPanel();
window.add(mainPanel);
window.setBackground(Color.BLACK);
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
mainPanel.startMainThread();
}
}
uj5u.com熱心網友回復:
所以是的,JLayeredPane 將允許 Swing 組件(如 JPanel)輕松重疊,并且還有其他人創建的布局允許這樣做,稱為“疊加布局”,但這不是您當前陳述的問題想要的。
你的問題是一個XY 問題型別的問題,當最好的解決方案不是以這種方式解決它,而是做 Y,完全不同的事情時,你會問“我如何解決 X 問題”。在這里,要繪制多個不同的影像,最好的解決方案不是創建和重疊 JPanel 等重量較重的 Swing 組件,而是繪制一個 JPanel 并重疊 sprite 影像。否則,您只會使您自己和您的代碼變得不必要地困難,而不是需要。
例如:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
public class Example2 extends JPanel {
private static final int MY_WIDTH = 1600;
private static final int MY_HEIGHT = 720;
List<Rectangle> rectangles = new ArrayList<>();
public Example2() {
setPreferredSize(new Dimension(MY_WIDTH, MY_HEIGHT));
setBackground(Color.WHITE);
rectangles.add(new Rectangle(0, 0, 200, 200));
rectangles.add(new Rectangle(0, 80 MY_HEIGHT / 2, 200, 200));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (Rectangle rectangle : rectangles) {
g2.fill(rectangle);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
Example2 example = new Example2();
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(example);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
是的,正如評論中所建議的那樣, override paintComponent,not paint。這降低了可能來自繪制子組件或邊框的不良副作用的風險,并且還允許在您執行影片時自動進行雙緩沖。
此外,while (true)在事件驅動的 GUI 程式中,回圈不是一個健康的構造,而不是像您撰寫的那樣。如果您需要在 Swing 程式中重復操作(在您的示例中不需要,目前還沒有),請改用Swing 計時器。
所以這樣做會給你很好的靈活性。例如,如果您想修改上述程式以允許在滑鼠單擊時添加形狀,這樣做很容易:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
@SuppressWarnings("serial")
public class Example3 extends JPanel {
private static final int MY_WIDTH = 1600;
private static final int MY_HEIGHT = 720;
List<ColorShape> colorShapes = new ArrayList<>();
public Example3() {
setPreferredSize(new Dimension(MY_WIDTH, MY_HEIGHT));
setBackground(Color.WHITE);
addMouseListener(new MyMouse());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (ColorShape colorShape : colorShapes) {
colorShape.draw(g2);
}
}
private class MyMouse extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
// create a random color
float hue = (float) Math.random();
float saturation = 1f;
float brightness = (float) (0.5 * Math.random() 0.5);
Color color = Color.getHSBColor(hue, saturation, brightness);
// create a new ColorShape, add to list, and repaint:
colorShapes.add(new ColorShape(e.getPoint(), color));
repaint();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
Example3 example = new Example3();
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(example);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
class ColorShape {
private int width = 80;
private Point location;
private Color color;
private Shape shape;
public ColorShape(Point location, Color color) {
this.location = location;
this.color = color;
int x = location.x - width / 2;
int y = location.y - width / 2;
shape = new Ellipse2D.Double(x, y, width, width);
}
public void draw(Graphics2D g2) {
g2.setColor(color);
g2.fill(shape);
}
public Point getLocation() {
return location;
}
}
uj5u.com熱心網友回復:
最后兩個引數setBounds(int x,int y, int width, int height)是面板的寬度和高度。在您的情況下,這些是矩形的尺寸,因此您應該將它們設定為200,如下所示:
overlappingPanel1.setBounds(0,0,200,200);
overlappingPanel2.setBounds(0,720/2,200,200);
此外,洗掉setPreferredSize(new Dimension(1920,720));和類OverlappingPanel1,OverlappingPanel2因為它們不是必需的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/420540.html
標籤:
