在下面的復制器中,我正在復制我在圖形界面中看到的內容。我想重新繪制畫布的臟區域(a JPanel),因為完全重新繪制會引入更多延遲。
但是,當呼叫重繪(臟矩形)函式時,它會導致嵌套的 Graphics2D 物件出現一些問題。特別是

此代碼可能會誤用剪輯邊界,但我沒想到在創建子(嵌套)圖形背景關系時會出現這種“工件”。
在這種情況下,處理剪輯、嵌套圖形背景關系和臟區域(或矩形)的正確方法是什么repaint。
我的直覺告訴我代碼應該在不使用剪切區域的情況下計算其形狀。
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Rectangle2D;
public class Reproducer {
public static void main(String[] args) {
var comp = new MyJPanel();
var timer = new Timer(2_000, e -> {
SwingUtilities.invokeLater(comp::bug);
});
timer.start();
timer.setRepeats(true);
SwingUtilities.invokeLater(() -> {
var frame = new JFrame("Reproducer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(300, 300));
frame.setVisible(true);
frame.getContentPane().add(comp);
});
}
private static class MyJPanel extends JPanel {
public MyJPanel() {
setSize(600, 600);
setPreferredSize(getSize());
}
@Override
protected void paintComponent(Graphics g) {
var g2 = (Graphics2D) g;
super.paintComponent(g2);
g2.setColor(Color.cyan);
g2.fill(g2.getClip());
var graphicsBox = (Graphics2D) g2.create(10, 10, 290, 290);
var clipBounds = graphicsBox.getClipBounds();
graphicsBox.setColor(Color.LIGHT_GRAY);
graphicsBox.setStroke(new BasicStroke(2));
graphicsBox.drawRect(clipBounds.x, clipBounds.y, clipBounds.width, clipBounds.height);
graphicsBox.setColor(Color.red);
graphicsBox.fill(new Rectangle2D.Double(clipBounds.x 2,
clipBounds.y 2,
clipBounds.width - 2,
clipBounds.height - 2));
graphicsBox.dispose();
var graphicsOverlay = (Graphics2D) g2.create(100, 100, 100, 100);
graphicsOverlay.setColor(Color.YELLOW);
graphicsOverlay.fillOval(10, 10, 60, 60);
graphicsOverlay.dispose();
}
public void bug() {
getVisibleRect();
repaint(100, 100, 100, 100);
}
}
}
通過移動fill上面進行編輯drawRect

uj5u.com熱心網友回復:
所以,有幾個“錯誤”
我找到了這個...
graphicsBox.drawRect(clipBounds.x, clipBounds.y, clipBounds.width, clipBounds.height);
graphicsBox.setColor(Color.red);
graphicsBox.fill(new Rectangle2D.Double(clipBounds.x 2,
clipBounds.y 2,
clipBounds.width - 2,
clipBounds.height - 2));
有點錯誤,這意味著當應用剪輯時,背景區域沒有被正確填充。
呼叫super.paintComponent是用組件的背景顏色填充剪輯區域,但graphicsBox.fill沒有填充整個區域,允許看到部分背景顏色。
我還發現結果Graphics2D#create(int, int, int, int)有點令人驚訝
新的 Graphics 物件將其原點轉換為指定的點 (x, y)。其剪輯區域由原始剪輯區域與指定矩形的交點確定。
(重點由我添加)
我的意思是,老實說,我不應該感到驚訝,但我以前從未使用過這些功能,所以這讓我有點驚訝。
所以,我更正了graphicsBox渲染代碼,以便fill首先填充整個剪切區域,然后繪制矩形(在邊界矩形內)
var graphicsBox = (Graphics2D) g2.create(10, 10, 290, 290);
var clipBounds = graphicsBox.getClipBounds();
graphicsBox.setColor(Color.red);
graphicsBox.fill(new Rectangle2D.Double(clipBounds.x,
clipBounds.y,
clipBounds.width,
clipBounds.height));
Collections.shuffle(colors);
graphicsBox.setColor(colors.get(0));
graphicsBox.setStroke(new BasicStroke(2));
graphicsBox.drawRect(clipBounds.x 1, clipBounds.y 1, clipBounds.width - 2, clipBounds.height - 2);
graphicsBox.dispose();
注意:對的參考colors只是Color我在繪制程序中隨機排列的 s 串列,所以我可以“看到”發生了什么
另一個技巧可能是更改組件的背景顏色,以便更容易“看到”錯誤更新的地方。
當你遇到這樣的問題時,減少混亂的數量非常重要,看看你是否可以縮小問題的范圍,我拿出了大部分的繪制代碼來找出所有這些“小”的東西,它們結合起來會給你帶來問題.
可運行的示例...

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Main {
public static void main(String[] args) {
var comp = new MyJPanel();
var timer = new Timer(2_000, e -> {
SwingUtilities.invokeLater(comp::bug);
});
timer.start();
timer.setRepeats(true);
SwingUtilities.invokeLater(() -> {
var frame = new JFrame("Reproducer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(300, 300));
frame.setVisible(true);
frame.getContentPane().add(comp);
});
}
private static class MyJPanel extends JPanel {
private List<Color> colors;
public MyJPanel() {
setSize(600, 600);
setPreferredSize(getSize());
colors = Arrays.asList(new Color[] {
Color.BLACK,
Color.BLUE,
Color.CYAN,
Color.DARK_GRAY,
Color.GRAY,
Color.GREEN,
Color.LIGHT_GRAY,
Color.MAGENTA,
Color.ORANGE,
Color.PINK,
Color.RED,
Color.WHITE,
Color.YELLOW
});
}
@Override
protected void paintComponent(Graphics g) {
var g2 = (Graphics2D) g;
super.paintComponent(g2);
g2.setColor(Color.cyan);
g2.fill(g2.getClip());
var graphicsBox = (Graphics2D) g2.create(10, 10, 290, 290);
var clipBounds = graphicsBox.getClipBounds();
graphicsBox.setColor(Color.red);
graphicsBox.fill(new Rectangle2D.Double(clipBounds.x,
clipBounds.y,
clipBounds.width,
clipBounds.height));
Collections.shuffle(colors);
graphicsBox.setColor(colors.get(0));
graphicsBox.setStroke(new BasicStroke(2));
graphicsBox.drawRect(clipBounds.x 1, clipBounds.y 1, clipBounds.width - 2, clipBounds.height - 2);
graphicsBox.dispose();
var graphicsOverlay = (Graphics2D) g2.create(100, 100, 100, 100);
graphicsOverlay.setColor(Color.YELLOW);
graphicsOverlay.fillOval(10, 10, 60, 60);
graphicsOverlay.dispose();
}
public void bug() {
getVisibleRect();
repaint(100, 100, 100, 100);
}
}
}
如果您遇到“性能”問題,您可以考慮使用 aBufferedImage作為主要畫布并更新它,然后簡單地繪制影像。
或者,可能是時候改用 using 了BufferStrategy,這將使您盡可能接近 Java/Swing 允許的“金屬”
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/429896.html
下一篇:如何修改外觀系統類,例如com.sun.java.swing.plaf.windows.WindowsTableHeaderUI
