gpt4 book ai didi

multithreading - 从单个 "control"面板重新绘制多个 JPanel

转载 作者:行者123 更新时间:2023-12-02 07:27:01 26 4
gpt4 key购买 nike

所以我正在尝试设置一个应用程序,其中 jframe 内有多个面板。假设其中 3 个纯粹用于显示目的,其中一个用于控制目的。我正在使用 borderLayout 但我不认为布局应该真正影响这里的事情。

我的问题是这样的:我希望三个显示面板的重新绘制能够在控制面板中的按钮的控制下进行,并且我希望每当按下控制面板上的按钮时它们都会同步执行。为此,我设置了这个小方法:

public void update(){
while(ButtonIsOn){
a.repaint();
b.repaint()
c.repaint();
System.out.println("a,b, and c should have repainted");

}
}

其中 a、b 和 c 都是显示面板,我希望 a、b 和 c 全部连续重新绘制,直到我再次按下按钮。问题是,当我执行循环时,消息会在无限循环中打印,但没有一个面板执行任何操作,即没有一个面板重新绘制。

我一直在阅读事件调度线程和 Swing 多线程,但到目前为止我发现的任何内容都没有真正解决我的问题。有人可以告诉我我在这里做错了什么,或者更好的是,一些处理我所描述的情况的示例代码?谢谢...

最佳答案

java.util.concurrent包提供了非常强大的并发编程工具。

在下面的代码中,我使用了 ReentrantLock (其工作方式与 Java synchronized 关键字非常相似,确保多个线程对单个 block 的互斥访问)代码)。 ReentrantLock 提供的另一个伟大功能是条件,它允许线程 在继续之前等待特定事件。

这里,RepaintManager 只是循环,调用 JPanel 上的 repaint()。但是,当调用 toggleRepaintMode() 时,它会阻塞,等待 modeChanged Condition,直到再次调用 toggleRepaintMode()

您应该能够立即运行以下代码。按 JButton 切换 JPanel 的重新绘制(您可以通过 System.out.println 语句看到它的工作情况)。

总的来说,我强烈建议您熟悉 java.util.concurrent 的功能优惠。那里有很多非常强大的东西。 http://docs.oracle.com/javase/tutorial/essential/concurrency/ 有一个很好的教程

import java.awt.Component;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class RepaintTest {
public static void main(String[] args) {

JFrame frame = new JFrame();
JPanel panel = new JPanel()
{
@Override
public void paintComponent( Graphics g )
{
super.paintComponent( g );

// print something when the JPanel repaints
// so that we know things are working
System.out.println( "repainting" );
}
};

frame.add( panel );

final JButton button = new JButton("Button");
panel.add(button);

// create and start an instance of our custom
// RepaintThread, defined below
final RepaintThread thread = new RepaintThread( Collections.singletonList( panel ) );
thread.start();

// add an ActionListener to the JButton
// which turns on and off the RepaintThread
button.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent arg0) {
thread.toggleRepaintMode();
}
});

frame.setSize( 300, 300 );
frame.setVisible( true );
}

public static class RepaintThread extends Thread
{
ReentrantLock lock;
Condition modeChanged;
boolean repaintMode;
Collection<? extends Component> list;

public RepaintThread( Collection<? extends Component> list )
{
this.lock = new ReentrantLock( );
this.modeChanged = this.lock.newCondition();

this.repaintMode = false;
this.list = list;
}

@Override
public void run( )
{
while( true )
{
lock.lock();
try
{
// if repaintMode is false, wait until
// Condition.signal( ) is called
while ( !repaintMode )
try { modeChanged.await(); } catch (InterruptedException e) { }
}
finally
{
lock.unlock();
}

// call repaint on all the Components
// we're not on the event dispatch thread, but
// repaint() is safe to call from any thread
for ( Component c : list ) c.repaint();

// wait a bit
try { Thread.sleep( 50 ); } catch (InterruptedException e) { }
}
}

public void toggleRepaintMode( )
{
lock.lock();
try
{
// update the repaint mode and notify anyone
// awaiting on the Condition that repaintMode has changed
this.repaintMode = !this.repaintMode;
this.modeChanged.signalAll();
}
finally
{
lock.unlock();
}
}
}
}

关于multithreading - 从单个 "control"面板重新绘制多个 JPanel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10068455/

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