下面的代码应该与您在FF,IE或Chrome等浏览器中看到的多文档界面(MDI)有点相似。它在选项卡式窗格中显示“文档”(黑色缓冲图像作为间隔符),以便用户可以将它们从窗格拖动到新(或现有)窗口中。
但是,一旦它们没有更多选项卡,它就会关闭帧,以及在没有其他可见窗口时关闭JVM。我认为我通过Timer
中的DragTabManager
检查来解决这些问题:
DragTabFrame
Timer
以允许JRE退出。至少应该如何运作。它似乎在这里可靠地工作,并且我看到没有'空框架或VM无法关闭'进行了相当多的测试。它是否像其他人一样宣传,还是需要进一步观察?
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class DragTabFrame extends JFrame {
private JTabbedPane tabbedPane = new JTabbedPane();
private final static DragTabManager dragTabManager = new DragTabManager();
final MouseAdapter ma = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
JComponent c = (JComponent) e.getSource();
dragTabManager.setCurrentComponent(c);
DragTabFrame dtf = (DragTabFrame)c.getTopLevelAncestor();
dragTabManager.setCurrentFrame(dtf);
JTabbedPane tp = dtf.getTabbedPane();
int index = tp.indexOfComponent(c);
if (index<0) index = 0;
String title = tp.getTitleAt(index);
dragTabManager.setCurrentTitle(title);
}
@Override
public void mousePressed(MouseEvent e) {
JComponent c = (JComponent) e.getSource();
DragTabFrame dtf = (DragTabFrame)c.getTopLevelAncestor();
dragTabManager.setCurrentComponent(c);
dragTabManager.setCurrentFrame(dtf);
JTabbedPane tp = dtf.getTabbedPane();
int index = tp.indexOfComponent(c);
if (index<0) index = 0;
String title = tp.getTitleAt(index);
dragTabManager.setCurrentTitle(title);
}
@Override
public void mouseReleased(MouseEvent e) {
JComponent c = (JComponent) e.getSource();
if (c.getTopLevelAncestor().getBounds().contains(e.getLocationOnScreen())) {
// do nothing, the drop point is the same frame
} else {
DragTabFrame dtf = getTargetFrame(e.getLocationOnScreen());
if (dtf == null) {
dtf = new DragTabFrame();
dtf.init();
dtf.setLocation(e.getLocationOnScreen());
} else {
DragTabFrame fromFrame = dragTabManager.getCurrentFrame();
fromFrame.removeTabComponent(c);
JTabbedPane tp = fromFrame.getTabbedPane();
if (tp.getTabCount() == 0) {
fromFrame.setVisible(false);
fromFrame.dispose();
}
}
dtf.addTabComponent(dragTabManager.getCurrentTitle(), c);
dtf.pack();
dtf.setVisible(true);
}
}
};
public JTabbedPane getTabbedPane() {
return tabbedPane;
}
public DragTabFrame getTargetFrame(Point p) {
Frame[] frames = Frame.getFrames();
for (Frame frame : frames) {
if (frame instanceof DragTabFrame
&& frame.getBounds().contains(p)) {
return (DragTabFrame) frame;
}
}
return null;
}
public void init() {
// the GUI as seen by the user (without frame)
JPanel gui = new JPanel(new BorderLayout());
gui.setBorder(new EmptyBorder(2, 3, 2, 3));
gui.add(tabbedPane, BorderLayout.CENTER);
add(gui);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// See https://stackoverflow.com/a/7143398/418556 for demo.
setLocationByPlatform(true);
}
public void addTabComponent(String name, Component c) {
tabbedPane.addTab(name, c);
c.addMouseListener(ma);
c.addMouseMotionListener(ma);
}
public void removeTabComponent(Component c) {
tabbedPane.remove(c);
c.removeMouseListener(ma);
c.removeMouseMotionListener(ma);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
DragTabFrame dtf = new DragTabFrame();
dtf.init();
BufferedImage bi = new BufferedImage(
200, 40, BufferedImage.TYPE_INT_RGB);
for (int ii = 1; ii < 4; ii++) {
JLabel l = new JLabel(new ImageIcon(bi));
dtf.addTabComponent("Tab " + ii, l);
}
dtf.pack();
// should be done last, to avoid flickering, moving,
// resizing artifacts.
dtf.setVisible(true);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}
class DragTabManager {
private DragTabFrame currentFrame;
private JComponent currentComponent;
private String currentTitle;
private Timer timer;
public DragTabManager() {
ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Frame[] frames = Frame.getFrames();
if (frames.length==0) {
timer.stop();
}
System.out.println("frames.length: " + frames.length);
boolean allInvisible = true;
for (Frame frame : frames) {
if (frame instanceof DragTabFrame) {
DragTabFrame dtf = (DragTabFrame)frame;
if (dtf.isVisible()) {
allInvisible = false;
}
if (dtf.getTabbedPane().getTabCount()==0) {
dtf.setVisible(false);
dtf.dispose();
}
}
}
if (allInvisible) {
timer.stop();
}
}
};
timer = new Timer(200,actionListener);
timer.start();
}
/**
* @return the currentFrame
*/
public DragTabFrame getCurrentFrame() {
return currentFrame;
}
/**
* @param currentFrame the currentFrame to set
*/
public void setCurrentFrame(DragTabFrame currentFrame) {
this.currentFrame = currentFrame;
}
/**
* @return the currentComponent
*/
public JComponent getCurrentComponent() {
return currentComponent;
}
/**
* @param currentComponent the currentComponent to set
*/
public void setCurrentComponent(JComponent currentComponent) {
this.currentComponent = currentComponent;
}
/**
* @return the currentTitle
*/
public String getCurrentTitle() {
return currentTitle;
}
/**
* @param currentTitle the currentTitle to set
*/
public void setCurrentTitle(String currentTitle) {
this.currentTitle = currentTitle;
}
}
根据answer of DSquare中的建议,这里是固定来源,还有其他一些调整。
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class DragTabFrame extends JFrame {
private JTabbedPane tabbedPane = new JTabbedPane();
private final static DragTabManager dragTabManager = new DragTabManager();
final MouseAdapter ma = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
JComponent c = (JComponent) e.getSource();
DragTabFrame dtf = (DragTabFrame) c.getTopLevelAncestor();
dragTabManager.setCurrentComponent(c);
dragTabManager.setCurrentFrame(dtf);
JTabbedPane tp = dtf.getTabbedPane();
int index = tp.indexOfComponent(c);
String title = tp.getTitleAt(index);
dragTabManager.setCurrentTitle(title);
}
@Override
public void mouseReleased(MouseEvent e) {
JComponent c = (JComponent) e.getSource();
if (c.getTopLevelAncestor().getBounds().contains(
e.getLocationOnScreen())) {
// do nothing, the drop point is the same frame
} else {
DragTabFrame dtf = getTargetFrame(e.getLocationOnScreen());
if (dtf == null) {
dtf = new DragTabFrame();
dtf.init();
dtf.setLocation(e.getLocationOnScreen());
}
DragTabFrame fromFrame = dragTabManager.getCurrentFrame();
fromFrame.removeTabComponent(c);
JTabbedPane tp = fromFrame.getTabbedPane();
if (tp.getTabCount() == 0) {
fromFrame.setVisible(false);
fromFrame.dispose();
}
dtf.addTabComponent(dragTabManager.getCurrentTitle(), c);
dtf.pack();
dtf.setVisible(true);
}
}
};
public JTabbedPane getTabbedPane() {
return tabbedPane;
}
public DragTabFrame getTargetFrame(Point p) {
Frame[] frames = Frame.getFrames();
for (Frame frame : frames) {
if (frame instanceof DragTabFrame
&& frame.getBounds().contains(p)) {
return (DragTabFrame) frame;
}
}
return null;
}
public void init() {
// the GUI as seen by the user (without frame)
JPanel gui = new JPanel(new BorderLayout());
gui.setBorder(new EmptyBorder(2, 3, 2, 3));
gui.add(tabbedPane, BorderLayout.CENTER);
add(gui);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// See https://stackoverflow.com/a/7143398/418556 for demo.
setLocationByPlatform(true);
}
public void addTabComponent(String name, Component c) {
tabbedPane.addTab(name, c);
c.addMouseListener(ma);
c.addMouseMotionListener(ma);
}
public void removeTabComponent(Component c) {
tabbedPane.remove(c);
c.removeMouseListener(ma);
c.removeMouseMotionListener(ma);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
DragTabFrame dtf = new DragTabFrame();
dtf.init();
BufferedImage bi = new BufferedImage(
200, 40, BufferedImage.TYPE_INT_RGB);
for (int ii = 1; ii < 4; ii++) {
JLabel l = new JLabel(new ImageIcon(bi));
dtf.addTabComponent("Tab " + ii, l);
}
dtf.pack();
dtf.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
class DragTabManager {
private DragTabFrame currentFrame;
private JComponent currentComponent;
private String currentTitle;
/**
* @return the currentFrame
*/
public DragTabFrame getCurrentFrame() {
return currentFrame;
}
/**
* @param currentFrame the currentFrame to set
*/
public void setCurrentFrame(DragTabFrame currentFrame) {
this.currentFrame = currentFrame;
}
/**
* @return the currentComponent
*/
public JComponent getCurrentComponent() {
return currentComponent;
}
/**
* @param currentComponent the currentComponent to set
*/
public void setCurrentComponent(JComponent currentComponent) {
this.currentComponent = currentComponent;
}
/**
* @return the currentTitle
*/
public String getCurrentTitle() {
return currentTitle;
}
/**
* @param currentTitle the currentTitle to set
*/
public void setCurrentTitle(String currentTitle) {
this.currentTitle = currentTitle;
}
}
答案 0 :(得分:7)
取消激活计时器,我发现的不一致是将最后一个标签拖动到新的(不存在的)框架中。这是因为一个糟糕的其他地方没有让负责检查和关闭原始Frame的代码运行。我已经像这样修改了它,到目前为止它没有计时器:
@Override
public void mouseReleased(MouseEvent e) {
JComponent c = (JComponent) e.getSource();
if (c.getTopLevelAncestor().getBounds().contains(e.getLocationOnScreen())) {
// do nothing, the drop point is the same frame
} else {
DragTabFrame dtf = getTargetFrame(e.getLocationOnScreen());
if (dtf == null) {
dtf = new DragTabFrame();
dtf.init();
dtf.setLocation(e.getLocationOnScreen());
}// else {
DragTabFrame fromFrame = dragTabManager.getCurrentFrame();
fromFrame.removeTabComponent(c);
JTabbedPane tp = fromFrame.getTabbedPane();
if (tp.getTabCount() == 0) {
fromFrame.setVisible(false);
fromFrame.dispose();
}
//}
dtf.addTabComponent(dragTabManager.getCurrentTitle(), c);
dtf.pack();
dtf.setVisible(true);
}
}
[...]
public DragTabManager() {
/* unused actionlistener code here */
//timer = new Timer(200,actionListener);
//timer.start();
}
我不认为应该有任何其他问题,但我不知道你提到的关闭JVM问题。