swing 怎么让Popup和JPanel自动调整大小和位置

时间:2022-09-11 13:37:08

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;


public class MutiProgressBar extends JFrame {

private DefaultTableModel dtm;
private JTable tbl;
private JLabel statusLab;
private JScrollPane jsp;
private ProgressPan proPan;
private Popup popup;
private PopupFactory popupFatory = PopupFactory.getSharedInstance();

public MutiProgressBar() {
initComponents();
addListeners();
}

private void initComponents() {
JPanel pan = new JPanel();
pan.setOpaque(true);
setContentPane(pan);

jsp = new JScrollPane();
pan.setLayout(new BorderLayout());
pan.add(jsp, BorderLayout.CENTER);

JPanel statusPan = new JPanel();
statusPan.setPreferredSize(new Dimension(500, 20));
statusPan.setLayout(new BorderLayout());
statusPan.add(new JPanel(), BorderLayout.CENTER);
statusLab = new JLabel();
statusLab.setEnabled(false);
statusLab.setPreferredSize(new Dimension(200, 20));
statusLab.setBorder(BorderFactory.createEtchedBorder(Color.lightGray, Color.yellow));
statusLab.setText("0 Jobs are running...");
statusPan.add(statusLab, BorderLayout.EAST);
pan.add(statusPan, BorderLayout.SOUTH);


String[][] data = {{"R1C1", "R1C2"}, {"R2C1", "R2C2"}, {"R3C1", "R3C2"}};
String[] header = {"Column1", "Column2"};
dtm = new DefaultTableModel(data, header) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
tbl = new JTable(dtm);
jsp.setViewportView(tbl);
proPan = new ProgressPan();
}

private void addListeners() {
statusLab.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent evt) {
if (popup == null) {
popup = popupFatory.getPopup(MutiProgressBar.this, proPan, statusLab.getLocationOnScreen().x, statusLab.getLocationOnScreen().y - proPan.size.height);
popup.show();
} else {
popup.hide();
popup = null;
}
}
});

tbl.addMouseListener(new MouseAdapter() {
@Override
/*
 * 鼠标事件触发添加任务
 */
public void mouseClicked(MouseEvent evt) {
if (tbl.getSelectedRow() != -1) {
Task task = new Task(tbl.getSelectedRow() + tbl.getSelectedColumn(), evt.getPoint().toString().substring(21));
task.start();
}
}
});
}

private static void createAndShowGui() {
MutiProgressBar frame = new MutiProgressBar();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setMinimumSize(new Dimension(500, 400));
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGui();
}
});
}

class ProgressPan extends JPanel {
public Dimension size = new Dimension(200, 0);
private HashMap<String, JProgressBar> tasks = new HashMap();

public ProgressPan() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setOpaque(true);
}

public void addTask(String taskName) {
if (tasks.containsKey(taskName)) {
return;
}
JProgressBar task = new TaskBar(taskName);
task.setMinimumSize(new Dimension(200, 24));
task.setMaximumSize(new Dimension(200, 24));
task.setStringPainted(true);
tasks.put(taskName, task);
this.add(task);
size.height += 24;
this.setPreferredSize(size);
statusLab.setText(tasks.size() + "Jobs are running...");
}

public void removeTask(String taskName) {
if (tasks.containsKey(taskName)) {
this.remove(tasks.get(taskName));
tasks.remove(taskName);
size.height -= 24;
this.repaint();
statusLab.setText(tasks.size() + "Jobs are running...");
}
}

public void setValue(int value, String taskName) {
JProgressBar pb = tasks.get(taskName);
if (pb != null) {
pb.setValue(value);
}
}
}

/*
 * 模拟任务线程
 */
class Task extends Thread {
private int level;
private String taskName;

public Task(int level, String taskName) {
this.level = level;
this.taskName = taskName;
}

@Override
public void run() {
proPan.addTask(taskName);
for (int i = 0; i < 100; i++) {
proPan.setValue(i, taskName);
try {
Thread.sleep(level * 50);
} catch (InterruptedException ex) {
Logger.getLogger(MutiProgressBar.class.getName()).log(Level.SEVERE, null, ex);
}
}
proPan.removeTask(taskName);
}
}

class TaskBar extends JProgressBar {

private String taskName;

public TaskBar(String taskName) {
this.taskName = taskName;
}

@Override
public String getString() {
return taskName + ":" + super.getString();
}
}
}

怎么样让显示进度条的Panel自动调整大小和位置,始终粘在statusLab上面。。

4 个解决方案

#1


你代码中的注释太少了。
“显示进度条的Panel自动调整大小和位置”是什么意思?是在线程中对该JPanel进行修改么?
粘在statusLab上面。。
这句话指的是覆盖住 tatusLab吧?
粘这个字我真没明白什么意思。

#2


引用 1 楼 AA5279AA 的回复:
你代码中的注释太少了。
“显示进度条的Panel自动调整大小和位置”是什么意思?是在线程中对该JPanel进行修改么?
粘在statusLab上面。。
这句话指的是覆盖住 tatusLab吧?
粘这个字我真没明白什么意思。

这个能跑起来的 table的鼠标事件会产生一个任务(走进度条)。然后鼠标进入statusLab区域会显示那些进度条。离开消失。现在的问题是如果正在显示的进度条走完还是占用Popup的的contentPanel的位置。粘。。。不管JFrame怎么动,Popup出来的panel的绝对坐标要跟着statusLab走。。

#3


你把Popup添加到statusLab这个JLabel上了吧?
Popup不想看见的话就Popup.setVisible(false);啊,这样就不显示了。
至于你的那个思路,还是不太懂。
Popup是一个什么?
 pan.setLayout(new BorderLayout()); 
你默认布局是BorderLayout()
如果各个组件因为大小的改变而坐标一直变动的话,建议用绝对布局。

#4


引用 3 楼 AA5279AA 的回复:
你把Popup添加到statusLab这个JLabel上了吧?
Popup不想看见的话就Popup.setVisible(false);啊,这样就不显示了。
至于你的那个思路,还是不太懂。
Popup是一个什么?
 pan.setLayout(new BorderLayout()); 
你默认布局是BorderLayout()
如果各个组件因为大小的改变而坐标……

大哥,说半天居然没用过Popup。。

#1


你代码中的注释太少了。
“显示进度条的Panel自动调整大小和位置”是什么意思?是在线程中对该JPanel进行修改么?
粘在statusLab上面。。
这句话指的是覆盖住 tatusLab吧?
粘这个字我真没明白什么意思。

#2


引用 1 楼 AA5279AA 的回复:
你代码中的注释太少了。
“显示进度条的Panel自动调整大小和位置”是什么意思?是在线程中对该JPanel进行修改么?
粘在statusLab上面。。
这句话指的是覆盖住 tatusLab吧?
粘这个字我真没明白什么意思。

这个能跑起来的 table的鼠标事件会产生一个任务(走进度条)。然后鼠标进入statusLab区域会显示那些进度条。离开消失。现在的问题是如果正在显示的进度条走完还是占用Popup的的contentPanel的位置。粘。。。不管JFrame怎么动,Popup出来的panel的绝对坐标要跟着statusLab走。。

#3


你把Popup添加到statusLab这个JLabel上了吧?
Popup不想看见的话就Popup.setVisible(false);啊,这样就不显示了。
至于你的那个思路,还是不太懂。
Popup是一个什么?
 pan.setLayout(new BorderLayout()); 
你默认布局是BorderLayout()
如果各个组件因为大小的改变而坐标一直变动的话,建议用绝对布局。

#4


引用 3 楼 AA5279AA 的回复:
你把Popup添加到statusLab这个JLabel上了吧?
Popup不想看见的话就Popup.setVisible(false);啊,这样就不显示了。
至于你的那个思路,还是不太懂。
Popup是一个什么?
 pan.setLayout(new BorderLayout()); 
你默认布局是BorderLayout()
如果各个组件因为大小的改变而坐标……

大哥,说半天居然没用过Popup。。