Using JSplitPane with an AWT component

不问归期 提交于 2019-12-22 08:41:32

问题


I have an AWT canvas which I cannot convert to a Swing component (it comes from VTK). I wish to display a few of these canvases inside of a JSplitPane. I've read about mixing heavy and light weight components in Java and know that it's a pain in the butt, but I don't have a choice. If I wrap the AWT canvas inside of a JPanel and then put that on the split pane the split pane doesn't function at all. However, if I put the AWT canvas inside of a JPanel and then that inside of a JScrollPane and then those scroll panes on the JSplitPane the split pane does function, but the AWT canvas components don't resize properly. I'm lost about how to get the AWT canvas components to resize properly when the JSplitPane's divider is moved. I can catch the divider moving operation and operate on the AWT canvases at that time, but I don't know what to do. I've tried calling invalidate() then validate() then repaint(), but that didn't work.

Any ideas?

Here's a example of the problem

import javax.swing.*;
import java.awt.*;

public class SwingAWTError {
    public static void main(String[] args) {
        Canvas leftCanvas = new Canvas();
        Canvas rightCanvas = new Canvas();
        leftCanvas.setBackground(Color.RED);
        rightCanvas.setBackground(Color.BLUE);

        JPanel leftPanel = new JPanel();
        JPanel rightPanel = new JPanel();
        leftPanel.setLayout(new BorderLayout());
        rightPanel.setLayout(new BorderLayout());
        leftPanel.add(leftCanvas, BorderLayout.CENTER);
        rightPanel.add(rightCanvas, BorderLayout.CENTER);

        JScrollPane leftScroll = new JScrollPane();
        JScrollPane rightScroll = new JScrollPane();
        leftScroll.getViewport().add(leftPanel);
        rightScroll.getViewport().add(rightPanel);

        JSplitPane split = new JSplitPane();
        split.setLeftComponent(leftScroll);
        split.setRightComponent(rightScroll);
        split.setDividerLocation(400);

        JFrame frame = new JFrame();
        frame.getContentPane().setLayout(new BorderLayout());
        frame.getContentPane().add(split, BorderLayout.CENTER);
        frame.setSize(800, 800);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

回答1:


It is a dirty way but this will solve it:

When you call pack() without resizing the window, not much happens. So, when you first resize the window and then call pack(), your components are correcly drawn. This means you can put this dirty method in your divider moved listener method:

frame.setPreferredSize(frame.getSize()); // store the current size to restore it after packing.
frame.setSize(frame.getWidth() + 1, frame.getHeight()); // resize it!!
frame.pack();

I don't know what it is exactly but it is a strange behavour in Java...
Hope this helps until you've found a better solution...




回答2:


You are kind of out of luck here. There's a pretty good article on this on the sun/oracle website: http://java.sun.com/products/jfc/tsc/articles/mixing/

Essentially it boils down to this guideline (taken from that link, under the z-ordering heading):

Do not mix lightweight (Swing) and heavyweight (AWT) components within a container where the lightweight component is expected to overlap the heavyweight one.

Edit: I kept browsing that site and came across another link, and it would appear that the situation has improved slightly: http://java.sun.com/developer/technicalArticles/GUI/mixing_components/ But I think your case is one of those listed at the bottom in the limitations section:

Limitations

A few situations are not supported:

* Non-opaque lightweight components that have translucent

pixels (0 < alpha < 255) are not supported. If a partially translucent lightweight component overlaps a heavyweight component, the heavyweight component will not show through.

* Embedded heavyweight components must belong to the process that

created the frame or applet. The heavyweight component must have a valid peer within the main process of the application (or applet).

* Advanced Swing key events, such as those events maintained in an

InputMap, might not work correctly where lightweight and heavyweight components are being mixed. There are no known workarounds.



来源:https://stackoverflow.com/questions/3999437/using-jsplitpane-with-an-awt-component

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!