Java下拉框JComboBox举例

本文介绍了一个基于Java的程序,该程序实现了一个简单的地区选择功能,通过使用JComboBox组件,用户可以选择不同的地区,并根据所选地区动态加载对应的城市列表。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Demo10 extends JFrame implements ActionListener {
 String s[] = { "吉林", "辽宁", "黑龙江" };
 String ss[][] = { { "吉林市", "长春市", "四平市" }, 
   { "沈阳市", "大连市", "锦州市" },
   { "佳木斯", "哈尔滨", "齐齐哈尔" } };
 JComboBox jb1 = new JComboBox(s);
 JComboBox jb2 = new JComboBox();
 JPanel panel = new JPanel();

 public Demo10() {
  panel.add(jb1);
  panel.add(jb2);
  jb1.addActionListener(this);
  this.getContentPane().add(panel);
  this.setBounds(100, 100, 300, 300);
  this.setDefaultCloseOperation(3);
  this.setVisible(true);

 }

 public static void main(String[] args) {
  new Demo10();
 }

 public void actionPerformed(ActionEvent e) {
  JComboBox temp = (JComboBox) e.getSource();
  String name = (String) temp.getSelectedItem();
  if(jb2.getItemCount()!=0){
   jb2.removeAllItems();
   jb2.updateUI();
   jb2.setSelectedItem("");
  }
  if(name.equals(s[0])){ 
   for(int i=0;i<3;i++){
    jb2.addItem(ss[0][i]);
   }
  }
  else if(name.equals(s[1])){
   for(int i=0;i<3;i++){
    jb2.addItem(ss[1][i]);
   }
  }
  else if(name.equals(s[2])){
   for(int i=0;i<3;i++){
    jb2.addItem(ss[2][i]);
   }
  }

 }

}
// 读者-写者问题的抽象基类,定义了接口和共享状态 abstract class ReaderWriterProblem { protected int readerCount = 0; // 当前正在读取的读者数量 protected int writerCount = 0; // 当前正在写入的写者数量(最多为1) protected int waitingWriters = 0; // 正在等待的写者数量 protected int waitingReaders = 0; // 正在等待的读者数量 // 抽象方法:读者开始读取(可能被阻塞) public abstract void startReading(int id) throws InterruptedException; // 抽象方法:读者结束读取 public abstract void stopReading(int id); // 抽象方法:写者开始写入(可能被阻塞) public abstract void startWriting(int id) throws InterruptedException; // 抽象方法:写者结束写入 public abstract void stopWriting(int id); } // 公平竞争策略实现:按请求顺序处理读者和写者,不偏袒任何一方 class FairCompetition extends ReaderWriterProblem { private final Object lock = new Object(); // 全局锁,用于同步所有操作 @Override public void startReading(int id) throws InterruptedException { synchronized (lock) { waitingReaders++; // 标记有新读者正在等待 // 等待条件:存在活跃写者 或 有写者正在等待 while (writerCount > 0 || waitingWriters > 0) { lock.wait(); // 当前线程挂起,释放锁 } waitingReaders--; // 等待结束,移除等待标记 readerCount++; // 增加活跃读者数量 } } @Override public void stopReading(int id) { synchronized (lock) { readerCount--; // 减少活跃读者数量 // 如果没有活跃读者了,唤醒所有等待的线程(读者和写者) if (readerCount == 0) { lock.notifyAll(); } } } @Override public void startWriting(int id) throws InterruptedException { synchronized (lock) { waitingWriters++; // 标记有新写者正在等待 // 等待条件:存在活跃读者 或 存在活跃写者 while (readerCount > 0 || writerCount > 0) { lock.wait(); // 当前线程挂起,释放锁 } waitingWriters--; // 等待结束,移除等待标记 writerCount++; // 增加活跃写者数量 } } @Override public void stopWriting(int id) { synchronized (lock) { writerCount--; // 减少活跃写者数量 // 写者完成后,唤醒所有等待的线程(读者和写者) lock.notifyAll(); } } } // 读者优先策略实现:允许并发读取,写者必须等待所有读者完成 class ReaderPriority extends ReaderWriterProblem { private final Object readLock = new Object(); // 读者锁,控制读者数量 private final Object writeLock = new Object(); // 写者锁,控制写者访问 @Override public void startReading(int id) throws InterruptedException { synchronized (readLock) { // 增加读者计数 readerCount++; // 如果是第一个读者,需要获取写锁以阻止写者进入 if (readerCount == 1) { synchronized (writeLock) { writeLock.wait(); // 第一个读者获取写锁并等待(实际是阻塞写者) } } } } @Override public void stopReading(int id) { synchronized (readLock) { // 减少读者计数 readerCount--; // 如果没有读者了,释放写锁,允许写者进入 if (readerCount == 0) { synchronized (writeLock) { writeLock.notify(); // 通知可能等待的写者 } } } } @Override public void startWriting(int id) throws InterruptedException { synchronized (writeLock) { // 增加写者计数 writerCount++; // 等待所有读者完成 while (readerCount > 0) { writeLock.wait(); } } } @Override public void stopWriting(int id) { synchronized (writeLock) { // 减少写者计数 writerCount--; // 通知可能等待的写者或读者 writeLock.notify(); } } } // 写者优先策略实现:写者获得更高优先级,减少写者饥饿 class WriterPriority extends ReaderWriterProblem { private final Object lock = new Object(); // 全局锁,用于同步所有操作 private int activeReaders = 0; // 当前活跃的读者数量 private int activeWriters = 0; // 当前活跃的写者数量(最多为1) private int waitingReaders = 0; // 等待的读者数量 private int waitingWriters = 0; // 等待的写者数量 @Override public void startReading(int id) throws InterruptedException { synchronized (lock) { waitingReaders++; // 标记有新读者正在等待 // 等待条件:存在活跃写者 或 有写者正在等待 while (activeWriters > 0 || waitingWriters > 0) { lock.wait(); // 当前线程挂起,释放锁 } waitingReaders--; // 等待结束,移除等待标记 activeReaders++; // 增加活跃读者数量 } } @Override public void stopReading(int id) { synchronized (lock) { activeReaders--; // 减少活跃读者数量 // 如果没有活跃读者了,唤醒所有等待的线程(优先处理写者) if (activeReaders == 0) { lock.notifyAll(); } } } @Override public void startWriting(int id) throws InterruptedException { synchronized (lock) { waitingWriters++; // 标记有新写者正在等待 // 等待条件:存在活跃读者 或 存在活跃写者 while (activeReaders > 0 || activeWriters > 0) { lock.wait(); // 当前线程挂起,释放锁 } waitingWriters--; // 等待结束,移除等待标记 activeWriters++; // 增加活跃写者数量 } } @Override public void stopWriting(int id) { synchronized (lock) { activeWriters--; // 减少活跃写者数量 // 写者完成后,唤醒所有等待的线程(优先处理写者) lock.notifyAll(); } } }// 主GUI界面类,继承自JFrame import javax.swing.*; import java.awt.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ReaderWriterGUI extends JFrame { private JTextArea logArea; // 日志显示区域 private JComboBox<String> strategyComboBox; // 策略选择下拉框 private JButton startButton; // 开始模拟按钮 private JSpinner readerSpinner; // 读者数量选择器 private JSpinner writerSpinner; // 写者数量选择器 private JPanel visualizationPanel; // 可视化面板,显示当前状态 private JTextField studentIdField; // 学号输入框 private JButton calculateButton; // 计算按钮 private JLabel resultLabel; // 结果标签 private JPanel resultPanel; // 结果显示面板 private JButton clearButton; // 清空按钮 private ReaderWriterProblem problem; // 当前选择的策略实现 private ExecutorService executor; // 线程池,用于管理读者和写者线程 // 构造函数:初始化GUI组件 public ReaderWriterGUI() { setTitle("读者-写者问题模拟器"); // 设置窗口标题 setSize(800, 700); // 设置窗口大小 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置关闭操作 setLayout(new BorderLayout()); // 设置布局管理器 // 初始化控制面板 JPanel controlPanel = new JPanel(new GridLayout(2, 1)); // 第一行:学号计算区域 JPanel studentIdPanel = new JPanel(); studentIdField = new JTextField(10); // 学号输入框,长度为10个字符 calculateButton = new JButton("计算余数"); // 计算按钮 resultLabel = new JLabel("结果将显示在这里"); // 结果标签 clearButton = new JButton("清空"); // 清空按钮 // 结果显示面板,用于展示计算结果 resultPanel = new JPanel(); resultPanel.setBackground(Color.WHITE); // 设置背景为白色 resultPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK)); // 添加黑色边框 resultPanel.setPreferredSize(new Dimension(50, 30)); // 设置首选大小 resultPanel.setLayout(new BorderLayout()); // 设置布局 JLabel resultValueLabel = new JLabel(" ", SwingConstants.CENTER); // 结果值标签,居中显示 resultPanel.add(resultValueLabel, BorderLayout.CENTER); // 将标签添加到面板中央 // 将组件添加到学号计算面板 studentIdPanel.add(new JLabel("学号尾数(后两位):")); studentIdPanel.add(studentIdField); studentIdPanel.add(calculateButton); studentIdPanel.add(resultLabel); studentIdPanel.add(resultPanel); studentIdPanel.add(clearButton); // 添加清空按钮 // 第二行:模拟控制面板 JPanel simulationPanel = new JPanel(); strategyComboBox = new JComboBox<>(new String[]{"公平竞争", "读者优先", "写者优先"}); // 策略选择下拉框 readerSpinner = new JSpinner(new SpinnerNumberModel(5, 1, 20, 1)); // 读者数量选择器,默认5,范围1-20 writerSpinner = new JSpinner(new SpinnerNumberModel(5, 1, 20, 1)); // 写者数量选择器,默认5,范围1-20 startButton = new JButton("开始模拟"); // 开始模拟按钮 // 将组件添加到模拟控制面板 simulationPanel.add(new JLabel("策略:")); simulationPanel.add(strategyComboBox); simulationPanel.add(new JLabel("读者数量:")); simulationPanel.add(readerSpinner); simulationPanel.add(new JLabel("写者数量:")); simulationPanel.add(writerSpinner); simulationPanel.add(startButton); // 将两个面板添加到控制面板 controlPanel.add(studentIdPanel); controlPanel.add(simulationPanel); // 初始化日志面板 logArea = new JTextArea(); // 创建文本区域 logArea.setEditable(false); // 设置为不可编辑 JScrollPane logScrollPane = new JScrollPane(logArea); // 添加滚动条 // 初始化可视化面板 visualizationPanel = new JPanel() { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (problem != null) { drawVisualization(g); // 绘制可视化内容 } } }; visualizationPanel.setPreferredSize(new Dimension(800, 200)); // 设置面板大小 // 将各面板添加到主窗口 add(controlPanel, BorderLayout.NORTH); // 控制面板放在顶部 add(logScrollPane, BorderLayout.CENTER); // 日志面板放在中央 add(visualizationPanel, BorderLayout.SOUTH); // 可视化面板放在底部 // 注册事件监听器 startButton.addActionListener(e -> startSimulation()); // 开始模拟按钮点击事件 calculateButton.addActionListener(e -> calculateRemainder()); // 计算按钮点击事件 clearButton.addActionListener(e -> clearAll()); // 清空按钮点击事件 } // 清空所有内容的方法 private void clearAll() { // 停止所有正在运行的线程 if (executor != null) { executor.shutdownNow(); executor = null; } // 清空日志区域 logArea.setText(""); // 重置学号计算结果 studentIdField.setText(""); resultLabel.setText("结果将显示在这里"); JLabel resultValueLabel = (JLabel)resultPanel.getComponent(0); resultValueLabel.setText(" "); resultPanel.revalidate(); // 重新验证面板布局 resultPanel.repaint(); // 重绘面板 // 重置模拟参数 strategyComboBox.setSelectedIndex(0); // 选择第一个策略(公平竞争) readerSpinner.setValue(5); // 重置读者数量为5 writerSpinner.setValue(5); // 重置写者数量为5 // 清空可视化面板 problem = null; visualizationPanel.repaint(); // 重绘可视化面板 } // 计算学号尾数余数的方法 private void calculateRemainder() { try { String idStr = studentIdField.getText(); // 获取输入的学号 // 验证输入长度 if (idStr.length() < 2) { JOptionPane.showMessageDialog(this, "请输入至少两位学号尾数", "错误", JOptionPane.ERROR_MESSAGE); return; } String lastTwoDigits = idStr.substring(idStr.length() - 2); // 获取最后两位数字 int number = Integer.parseInt(lastTwoDigits); // 转换为整数 int remainder = number % 3; // 计算除以3的余数 // 更新结果显示 resultLabel.setText("学号尾数 " + lastTwoDigits + " 除以3的余数是: "); JLabel resultValueLabel = (JLabel)resultPanel.getComponent(0); resultValueLabel.setText(String.valueOf(remainder)); resultPanel.revalidate(); // 重新验证面板布局 resultPanel.repaint(); // 重绘面板 // 根据余数自动选择策略 if (remainder == 0) { strategyComboBox.setSelectedIndex(0); // 公平竞争 } else if (remainder == 1) { strategyComboBox.setSelectedIndex(1); // 读者优先 } else if (remainder == 2) { strategyComboBox.setSelectedIndex(2); // 写者优先 } } catch (NumberFormatException e) { // 处理数字格式异常 JOptionPane.showMessageDialog(this, "请输入有效的数字", "错误", JOptionPane.ERROR_MESSAGE); } } // 开始模拟的方法 private void startSimulation() { // 如果有正在运行的线程,先停止它们 if (executor != null) { executor.shutdownNow(); } // 根据选择的策略创建相应的问题实例 int strategyIndex = strategyComboBox.getSelectedIndex(); switch (strategyIndex) { case 0: problem = new FairCompetition(); break; // 公平竞争策略 case 1: problem = new ReaderPriority(); break; // 读者优先策略 case 2: problem = new WriterPriority(); break; // 写者优先策略 } // 获取读者和写者的数量 int readerCount = (int) readerSpinner.getValue(); int writerCount = (int) writerSpinner.getValue(); // 创建线程池,用于管理读者和写者线程 executor = Executors.newFixedThreadPool(readerCount + writerCount); // 创建并提交读者线程 for (int i = 0; i < readerCount; i++) { final int id = i; // 线程ID executor.execute(() -> { try { problem.startReading(id); // 尝试开始读取 log("读者 " + id + " 开始进行读操作"); // 记录日志 visualizationPanel.repaint(); // 刷新可视化面板 Thread.sleep((long) (Math.random() * 3000)); // 模拟读取时间 problem.stopReading(id); // 结束读取 log("读者 " + id + " 读操作结束"); // 记录日志 visualizationPanel.repaint(); // 刷新可视化面板 } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复中断状态 } }); } // 创建并提交写者线程 for (int i = 0; i < writerCount; i++) { final int id = i; // 线程ID executor.execute(() -> { try { problem.startWriting(id); // 尝试开始写入 log("写者 " + id + " 开始进行写操作"); // 记录日志 visualizationPanel.repaint(); // 刷新可视化面板 Thread.sleep((long) (Math.random() * 3000)); // 模拟写入时间 problem.stopWriting(id); // 结束写入 log("写者 " + id + " 写操作结束"); // 记录日志 visualizationPanel.repaint(); // 刷新可视化面板 } catch (InterruptedException e) { Thread.currentThread().interrupt(); // 恢复中断状态 } }); } } // 记录日志的方法(确保在事件调度线程中执行) private void log(String message) { SwingUtilities.invokeLater(() -> { logArea.append(message + "\n"); // 添加日志内容 logArea.setCaretPosition(logArea.getDocument().getLength()); // 滚动到最新内容 }); } // 绘制可视化内容的方法(当前为空,需要实现) private void drawVisualization(Graphics g) { // 实现图形化表示当前读者和写者的状态 } // 主方法:程序入口点 public static void main(String[] args) { // 在事件调度线程中创建和显示GUI SwingUtilities.invokeLater(() -> { ReaderWriterGUI gui = new ReaderWriterGUI(); gui.setVisible(true); // 显示窗口 }); } }修改这个代码使得读者优先模式 的输出结果为读者4 开始进行读操作 写者2 文件被读者或写者占用,请等待 读者1 开始进行读操作 写者4 文件被读者或写者占用,请等待 写者5 文件被读者或写者占用,请等待 读者1 读操作结束 写者2 文件被读者或写者占用,请等待 写者5 文件被读者或写者占用,请等待 写者4 文件被读者或写者占用,请等待 写者1 文件被读者或写者占用,请等待 读者4 读操作结束 此时无读者在线,文件空闲中 写者2 开始进行写操作 写者1 文件被读者或写者占用,请等待 写者4 文件被读者或写者占用,请等待 写者5 文件被读者或写者占用,请等待 写者3 文件被读者或写者占用,请等待 。。。。。,只是举例了一个读者优先模式的输出结果,修改代码使得呈现完整的三种模式输出结果,而且保留GUI的页面设计
最新发布
06-01
### 读者-写者问题的代码调整与GUI设计 为了实现公平竞争、读者优先和写者优先三种模式,并在GUI界面中展示详细输出日志,可以按照以下方法调整代码结构。以下是详细的解决方案: #### 1. 模式选择逻辑 通过定义三个不同的锁机制来分别实现公平竞争、读者优先和写者优先[^1]。每种模式都需要单独的逻辑控制以确保符合特定规则。 ```python import threading import time from tkinter import Tk, Text, Button # 定义全局变量 reader_count = 0 mutex = threading.Lock() room_empty = threading.Lock() writer_lock = threading.Lock() # 公平竞争模式 def fair_mode(): room_empty.acquire() global reader_count if reader_count == 0: writer_lock.acquire() mutex.acquire() reader_count += 1 mutex.release() room_empty.release() # 模拟读操作 print("Reader is reading in FAIR mode.") time.sleep(1) mutex.acquire() reader_count -= 1 if reader_count == 0: writer_lock.release() mutex.release() # 读者优先模式 def reader_preferred_mode(): mutex.acquire() global reader_count reader_count += 1 if reader_count == 1: writer_lock.acquire() mutex.release() # 模拟读操作 print("Reader is reading in READER-PREFERRED mode.") time.sleep(1) mutex.acquire() reader_count -= 1 if reader_count == 0: writer_lock.release() mutex.release() # 写者优先模式 def writer_preferred_mode(): writer_lock.acquire() # 模拟写操作 print("Writer is writing in WRITER-PREFERRED mode.") time.sleep(2) writer_lock.release() ``` #### 2. GUI界面设计 使用`tkinter`库创建一个简单的GUI界面,允许用户选择模式并查看输出日志。 ```python class ReaderWriterApp: def __init__(self, root): self.root = root self.log_text = Text(self.root, height=10, width=50) self.log_text.pack() Button(self.root, text="Fair Mode", command=self.run_fair).pack() Button(self.root, text="Reader Preferred", command=self.run_reader_preferred).pack() Button(self.root, text="Writer Preferred", command=self.run_writer_preferred).pack() def log(self, message): self.log_text.insert('end', message + '\n') self.log_text.see('end') def run_fair(self): threading.Thread(target=fair_mode).start() self.log("Started FAIR mode.") def run_reader_preferred(self): threading.Thread(target=reader_preferred_mode).start() self.log("Started READER-PREFERRED mode.") def run_writer_preferred(self): threading.Thread(target=writer_preferred_mode).start() self.log("Started WRITER-PREFERRED mode.") if __name__ == "__main__": root = Tk() app = ReaderWriterApp(root) root.mainloop() ``` #### 3. 输出结果 在GUI界面上,点击不同的按钮会触发相应的模式,同时将日志信息输出到文本框中,便于用户观察运行状态。此设计保留了原有的GUI布局,并添加了模式切换功能。 ####
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值