我已经在JScrollPane中放置了一个JPanel对象,滚动工作就像预期的那样。通过重写paintComponent(),我尝试在JPanel对象中进行自定义绘制。然而,当JPanel对象放置在JScrollPane中时,JPanel不再正确地绘制(而是只显示其背景颜色)。
因为我的应用程序要求JPanel不断更新,所以构造了一个单独的线程,以在特定的时间间隔重新绘制JPanel。
以下代码摘录显示了我当前的项目:
a)来自我的JPanel的paintComponent()(此方法已被削减为只有绘画,实际的绘画将是一个不断更新的BufferedImage,由另一个线程提供,而不是这个粉红色的大静态框):
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
//Render Frame
// 'RXDisplayCanvas' is the JPanel.
Graphics2D G2D = (Graphics2D)RXDisplayCanvas.getGraphics();
G2D.setColor(Color.PINK);
//800 and 600 are arbitrary values for this example, real values are calculated at runtime. The value calculation code is verified to work (as its used elsewhere in a similar scenario)
G2D.fillRect(0, 0, 800, 600);
G2D.dispose();
}
b)定期重新绘制帧的“更新器”线程:
@Override
public void run() {
long MaxFrameTime;
long Time;
while(isVisible()){
// 'FPSLimit' is a integer value (default to 30)
MaxFrameTime = Math.round(1000000000.0 / FPSLimit);
Time = System.nanoTime();
try{
SwingUtilities.invokeAndWait(new Runnable(){
@Override
public void run() {
// 'RXDisplayCanvas' is the JPanel.
RXDisplayCanvas.repaint(); //When using this, the JPanel does not display correctly.
//RXDisplayCanvas.paintImmediately(0, 0, RXDisplayCanvas.getWidth(), RXDisplayCanvas.getHeight()); When using this, the JPanel renders correctly but flickers.
}
});
}catch(InterruptedException | InvocationTargetException e){}
Time = System.nanoTime() - Time;
if(Time < MaxFrameTime){
try{
Thread.sleep(Math.round((MaxFrameTime - Time)/1000000.0));
}catch(InterruptedException ex){}
}
}
}
我已经考虑到repaint()不会立即重新绘制屏幕,但问题在于屏幕的不正确呈现。当程序单独运行时,它只呈现JPanel的背景颜色,直到JScrollPane滚动,在其中它正确呈现一帧,然后下一个repaint()调用绘制不正确的显示。
当将repaint()切换为paintimedialty()(在节选b中)时,框架呈现正确,但存在严重的闪烁,它不断地在绘制背景色和绘制粉红色框之间交替。我已经尝试添加和删除布局管理器,禁用重绘管理器,以及为两个组件启用和禁用‘双缓冲’标志,所有这些都导致了上面提到的两种行为之一(只呈现背景或闪烁)。
在这个问题上有人能帮我吗?
注:我很清楚Java的变量命名惯例,因为这是一个私人项目,我选择用大写字母开头的变量名,因为我觉得这样看起来更好,请不要发表评论。
1)我不确定这一点:
public void paintComponent(Graphics g){
super.paintComponent(g);
// 'RXDisplayCanvas' is the JPanel.
Graphics2D G2D = (Graphics2D)RXDisplayCanvas.getGraphics();
..
G2D.dispose();
}
我建议这样做:
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D G2D = (Graphics2D)g;
G2D.setColor(Color.PINK);
G2D.fillRect(0, 0, 800, 600);
}
注意我是如何省略getGraphics
,而使用PaintComponent
的当前图形上下文传递的。
还请注意,我不调用g2d.dipose()
,因为这会导致问题,它只应该在graphic
上执行,您创建了component.getGraphics()
,但在您的情况下,您甚至不应该创建graphic
的上下文,因为它已经创建并传递给了paintComponent方法。(参见此类似问题)
2)不需要repaint()
的SwingUtilities.InvokExxx
块,因为它是线程安全的。但特别是不需要SwingUtilites.InvokeAndWait
(因为这是一个阻塞调用,并等待直到所有挂起的AWT事件得到处理并且run()方法完成),这是不好的,而且可能会添加到您看到的屏幕可视伪影。
3)我试过添加和删除布局管理器,禁用重绘管理器,以及为两个组件启用和禁用‘双缓冲’标志,所有这些都导致了上面提到的两种行为之一(只呈现背景或闪烁)。撤销所有这些,因为我看不出这对绘画有何影响。
如果我有一个SSCCE来说明不想要的行为,那会更有帮助。因为我可以尝试重现您的错误,但我很可能无法(由于应用于您的应用程序的特定条件,可能导致这些视觉伪影)
问题内容: 我有一个JFrame,在这个JFrame中,我有一个绘制的JPanel,此Panel可以是任何大小,因此我将其放在JScrollpane中,以便当面板大于窗口屏幕大小时可以滚动。 不幸的是,它没有按我预期的那样工作: 使JFrame窗口小于JPanel大小不会显示滚动条 现在,JScrollPane的大小似乎已锁定为我添加到其中的JPanel的大小,就像以前一样,它的大小已调整为JFr
首先,我要说,我几乎可以保证这个问题是一个副本,但我找不到任何其他适合我的需要/在我的程序中工作的答案。我需要画一个,但我似乎无法画出显示所需的线条。 在我的中添加有什么问题吗?
我使用子JPanel构造JScrollPane,然后尝试将JScrollPane添加到父JPanel中,希望有一个可滚动的自定义JPanel。 我有一个大的细白线前面的所有我的组件,他们是没有滚动。有什么想法吗?
我想在我的基本框架中添加一个带有JPanel的JScrollpane 如果我将带有的直接添加到中,就可以了。但是现在,当我将帧的大小减小到500像素以下时,变得更小,如第二张图片所示。 如何使JScrollPane工作?
所以,我正在制作一种文本编辑器,我需要一个用于垂直导航的JScrollPane。但我不能让它工作。 我已经阅读了谷歌搜索结果前十页上的每一篇奇怪的教程,但我无法让它发挥作用。 假设我有JFrame(尺寸1000x800)。我想在其中放置一个JPanel(1000x2000),以便它与JFrame水平对齐。我想在JPanel的右侧粘贴一个简单的滚动条,这样就可以访问它的其余部分。 我减少了大小,我将
问题内容: 我如何告诉paint方法仅在JPanel上而不是在整个JFrame上绘制背景。我的JFrame大小大于JPanel。当我尝试为JPanel绘制网格背景时,网格似乎遍及整个JFrame,而不仅仅是JPanel。 以下是部分代码: 问题答案: camickr是正确的。所以: 您需要严格将工程图与不同组件分开。Swing已经在管理子组件,因此绝对不需要在Panel的Frame中实现图形(调用