gpt4 book ai didi

java - 非草率的设计模式,用于从Java中的其他线程更新GUI

转载 作者:行者123 更新时间:2023-12-03 12:53:54 24 4
gpt4 key购买 nike

与Java(Swing)中的其他线程打交道时,哪种设计模式最适合更新GUI?
例如,假设一个对象(如自定义JPanel)具有一个JList,该JList具有支持它的DefaultListModel。监听Socket的线程可以接收数据,然后希望从套接字上收到的信息中更新JList。
我了解SwingUtilities.invokeLater,但是这看起来像是段代码,因为实际上我有很多不同的函数可以(从非EDT线程调用)来操纵不同的GUI组件。
我想到的想法是使用ArrayBlockingQueue创建某种消息传递系统。基本上,我实现了Runnable,并在SwingUtilities.invokeLater方法调用中传递了this。然后执行该方法,但是它实际上并不知道该怎么办,但这就是我从安全的ArrayBlockingQueue线程弹出“消息”的地方。
有没有比这更好的设计模式?
我的基本JPanel类别

public class JPanelGUIThread extends JPanel implements Runnable
{
protected ArrayBlockingQueue<Object> guiUpdateMessages;

public JPanelGUIThread()
{
guiUpdateMessages = new ArrayBlockingQueue<Object>(10);
}

@Override
public void run()
{
while(guiUpdateMessages.size() > 0)
{
try
{
Object data = guiUpdateMessages.take();

if(data instanceof Object[])
{
handleGUIUpdateArray((Object[])data);
}
else
{
handleGUIUpdateObject(data);
}

}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}

public void handleGUIUpdateArray(Object[] objectArray)
{

}
public void handleGUIUpdateObject(Object object)
{

}
}

我的主要JPanel



public JLabel getChatLabel()
{
return chatLabel;
}

public JTextArea getChatArea()
{
return chatArea;
}

public JScrollPane getChatScrollPane()
{
return chatScrollPane;
}

public JTextField getMychat()
{
return mychat;
}

public JButton getSendButton()
{
return sendButton;
}

//This method is called from the EDT, so no need to perform adding messages
@Override
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == sendButton)
{
client.sendChatInformation(mychat.getText());
mychat.setText("");
}
}

public void clearOldChat()
{
Object[] data = new Object[3];
data[0] = chatArea;
data[1] = MessageType.SET;
data[2] = "";
guiUpdateMessages.add(data);
SwingUtilities.invokeLater(this);
}


@Override
public void handleGUIUpdateArray(Object[] objectArray)
{
if(objectArray[0] == chatArea)
{
if(objectArray[1] == MessageType.APPEND)
{
chatArea.append((String) objectArray[2]);
}
else if(objectArray[1] == MessageType.SET)
{
chatArea.setText((String) objectArray[2]);
}

}
}
}

最佳答案

您正在重新发明“事件队列”,它首先使图形用户界面工作。已经有一个队列,您可以在其中添加新消息,这是在 java.awt.EventQueue 类中实现的。
将消息添加到事件队列的便捷方法是使用 SwingUtilities.invokeLater(Runnable) 。您传入的Runnable实例应包含处理事件所需的所有信息。更好的是:由于它是Runnable,因此可以封装处理事件所需的代码。
例如:这是将常规的“对象数组”消息封装在Runnable中并将其添加到事件队列中的方法。

        public void clearOldChat() {
Object[] data = new Object[3];
data[0] = chatArea;
data[1] = MessageType.SET;
data[2] = "";
SwingUtilities.invokeLater(new GUIUpdateArrayHandler(data));
}

class GUIUpdateArrayHandler implements Runnable {

Object[] objectArray;

public GUIUpdateArray(Object[] objectArray) {
this.objectArray = objectArray;
}

public void run() {
if (objectArray[0] == chatArea) {
if (objectArray[1] == MessageType.APPEND) {
chatArea.append((String) objectArray[2]);
} else if (objectArray[1] == MessageType.SET) {
chatArea.setText((String) objectArray[2]);
}

}
}
}
就个人而言,我将为要发送的每种消息类型创建一个单独的“Runnable”类,而不是一个通用的 GUIUpdateArrayHandler:例如, AppendHandlerMessageType.APPENDSetHandlerMessageType.SET,但是如果您认为将它们放在同一个位置是“少草率”在一个处理程序中,由您决定。

关于java - 非草率的设计模式,用于从Java中的其他线程更新GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62927373/

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