I have a form stored in both the inputWidget and the outputWidget. The buttons addInput and addOutput will show two different forms in the secondaryInOutPanel.
However there is a significant delay when moving between the form by clicking the buttons. In fact it changes when I attempting to click on the form. And there is still some visible drawings from the pervious form.
I tried using SwingUtilities but that caused the delay to be worst.
secondaryInOutPanel = new JPanel(new BorderLayout());
secondaryInOutPanel.setMinimumSize(new Dimension(200,400));
JPanel btnPanel = new JPanel();
outinPanel.add(btnPanel, BorderLayout.NORTH);
JButton addInput = new JButton("Add Input");
btnPanel.add(addInput);
addInput.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
secondaryInOutPanel.removeAll();
secondaryInOutPanel.add(inputWidget, BorderLayout.NORTH);
JButton addBtn = new JButton("Save Input");
secondaryInOutPanel.add(addBtn, BorderLayout.SOUTH);
addBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
});
}
});
JButton addOutput = new JButton("Add Output");
btnPanel.add(addOutput);
addOutput.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
secondaryInOutPanel.removeAll();
secondaryInOutPanel.add(outputWidget, BorderLayout.NORTH);
JButton addBtn = new JButton("Save Output");
secondaryInOutPanel.add(addBtn, BorderLayout.SOUTH);
addBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
});
}
});
A better design is to use a Card Layout to hold your input and output panels. Then you can just swap panels as required. The CardLayout will then manage the revalidating and repainting of the panel for you.
You need to make a call to revalidate() and or repaint() on the secondaryInOutPanel after you make changes.
Related
I have JavaFX panel with ChoiceBox in Swing application. Standard behaviour of ChoiceBox is that when you click it for the first time the popup menu with items is shown and when you click ChoiceBox for the second time, the popup menu is hidden. But when you put it to Swing application the second click causes popup to hide and to be shown immediately again. How can I prevent this behaviour?
public class ComboTest {
private static void initAndShowGUI() {
JFrame frame = new JFrame("FX");
final JFXPanel fxPanel = new JFXPanel();
fxPanel.setPreferredSize(new Dimension(100, 100));
frame.add(fxPanel);
frame.pack();
frame.setVisible(true);
Platform.runLater(new Runnable() {
#Override
public void run() {
initFX(fxPanel);
}
});
}
private static void initFX(JFXPanel fxPanel) {
// This method is invoked on JavaFX thread
Scene scene = createScene();
fxPanel.setScene(scene);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
initAndShowGUI();
}
});
}
private static Scene createScene() {
ChoiceBox choiceBox = new ChoiceBox(FXCollections.observableArrayList("item 1", "item 2"));
VBox vbox = new VBox(choiceBox);
return new Scene(vbox);
}
}
My suspicion is that when I click the choicebox for the second time the popup loses focus which causes it to hide and the choicebox then handles mouse click and shows the popup again.
I believe that this problem caused by the existing ChoiceBox bug in javafx.
The simplest fix is just to use ComboBox instead:
ComboBox<String> choiceBox = new ComboBox<>(FXCollections.observableArrayList("item 1", "item 2"));
I have an JPanel populated with several opaque custom components. Now I would like to draw something on top of these components by overriding the paintComponent() method. My problem is that the painted stuff is placed behind the embedded components and, as they are opaque, is covered by them.
Is there any way to let the painting appear on top of the components?
Here's a short example of what I'm trying to do:
public class DrawOnTop {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame("Draw on top");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setVisible(true);
}
});
}
}
class MyPanel extends JPanel {
public MyPanel() {
setLayout(new BorderLayout(3, 3));
add(new JButton("Button 1"), BorderLayout.NORTH);
add(new JButton("Button 2"), BorderLayout.CENTER);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.drawLine(0, 0, getVisibleRect().width, getVisibleRect().height);
}
}
You were thinking along the right lines.
Only problem was that you should have Overridden the paintChildren() method like in the code below. This is because the paintComponent() method is called as first and does the background etc painting of the component itself (the MyPanel), then is called paintBorders() and lastly the paintChildren() which paints all that is inside of the component calling it.
public class DrawOnTop {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame("Draw on top");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setVisible(true);
}
});
}
}
class MyPanel extends JPanel {
public MyPanel() {
setLayout(new BorderLayout(3, 3));
JButton b1 = new JButton("Button 1");
MouseListener ml = new MouseAdapter() {
#Override
public void mouseExited(MouseEvent e) {
super.mouseExited(e);
MyPanel.this.repaint();
}
};
b1.addMouseListener(ml);
JButton b2 = new JButton("Button 2");
b2.addMouseListener(ml);
add(b1, BorderLayout.NORTH);
add(b2, BorderLayout.CENTER);
}
#Override
protected void paintChildren(Graphics g) {
super.paintChildren(g);
g.setColor(Color.red);
g.drawLine(0, 0, getVisibleRect().width, getVisibleRect().height);
}
}
Important to notice, in the code sample, that I added also a MouseListener to repaint the panel when a mouse exits a button, otherwise the buttons would always stay over the line once mouse enters over one of them.
But if you want to have a custom painting that is always on top of your components then I would suggest to use a glass pane. Examples of a glass pane use are provided here:
Simple one.
A more complex one.
I want to add a button to JTabbedPane's title bar (similar to the 'open new tab' ('+') button in Firefox)
I have tried to add to the glass pane of JTabbedPane's container. but since my tabbedpane contains within a JPanel seems it doesn't work for me.
Any suggestion will be a great help for me.
Thank you.
Instead of adding a button I have tried it in a different way and worked for me... I have added a JLabel (with '+') as a hidden tab and when user tries to select that tab i'll be adding a new tab.
public class AddTabButtonDemo extends JFrame{
private JTabbedPane tabbedPane = new JTabbedPane();
public AddTabButtonDemo() {
JLabel tab1Label = new JLabel("tab1");
JPanel tab1 = new JPanel();
tab1.add(tab1Label);
tabbedPane.addTab("tab1", tab1);
tabbedPane.addTab("+", new JLabel());
tabbedPane.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (tabbedPane.getSelectedComponent() instanceof JLabel) {
int count = tabbedPane.getTabCount();
JLabel newTabLabel = new JLabel("tab" + count);
JPanel newTab = new JPanel();
newTab.add(newTabLabel);
tabbedPane.add(newTab, count - 1);
tabbedPane.setTitleAt(count - 1, "tab" + count);
tabbedPane.setSelectedComponent(newTab);
}
}
});
this.add(tabbedPane, BorderLayout.CENTER);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setMinimumSize(new Dimension(300, 300));
this.setVisible(true);
}
public static void main(String[] args) {
new AddTabButtonDemo();
}
}
JButton btnCalendar = new JButton("Chart",new ImageIcon("new_chart.jpg"));
btnCalendar.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), "Chart clicked");
}
});
jToolBar1.add(btnCalendar);
jToolBar1.addSeparator();
I'm developing a Swing based application in which I want to add JToolBar with images in buttons.But images are not visible in the buttons
I face same problem and I resolved by
use of following code :
ImageIcon newImage= new ImageIcon(getClass().getResource("com/some/package/newItemImage.jpg"));
JButton newButton= new JButton(newImage);
this.add(newButton);
I have a question. Can I create glasspane in body MousePressed ? If yes anyone can write me how? I mean that I press mouse button and glass pane is visible and I can painting on him.
EDIT
Ok I have now what I want. My glass pane is creating when I click mouse button and disapear when I release this button. Now I have another question. Where I should create my painting method. I want draw rectangle on this glasss pane using mouse dragged. Where I must implement paint method? In other class or in this events? I implement one my try paint function but I don't know if this is good way. This is my code:
public class Selection extends JPanel
{
static Point startPoint;
public static void GUI()
{
final JFrame frame = new JFrame();
JPanel panel = new JPanel();
JButton button = new JButton("Select");
final JPanel glassPane = new JPanel();
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.add(button);
glassPane.setOpaque(false);
frame.add(panel);
frame.setGlassPane(glassPane);
glassPane.addMouseListener(new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent e)
{
super.mousePressed(e);
System.out.println("f.getGlassPane() mousePressed");
if(e.getButton() == MouseEvent.BUTTON1)
frame.getGlassPane().setVisible(true);
startPoint=e.getPoint();
Graphics2D g = null;
Graphics2D g2 = (Graphics2D) g;
Rectangle2D rect = new Rectangle2D.Double();
rect.setFrameFromDiagonal(e.getPoint().x, e.getPoint().y,startPoint.x, startPoint.y);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5F));
g2.setColor(Color.BLUE);
g2.fill(rect);
g2.draw(rect);
}
});
glassPane.addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseDragged(MouseEvent e)
{
}
#Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
});
frame.addMouseListener(new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent e)
{
super.mousePressed(e);
if(e.getButton() == MouseEvent.BUTTON1)
frame.getGlassPane().setVisible(true);
}
public void mouseReleased(MouseEvent e)
{
frame.getGlassPane().setVisible(false);
}
});
frame.setVisible(true);
}
int x1, x2, y1,y2;
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
g2.drawRect(x1,y1, x2, y2);
}
public static void main(String[] args)
{
GUI();
}
}
Hi please check out my answer to some other question where I present a way in which a glass pane can be used to simulated dialog behaviour. There you have shown how to show it and hide it on mouse click in my case right mouse click. This example should get you started nicely.
I see no problem creating a glasspane and attaching it to a RootPaneContainer from inside moussePressed() method.
However, I may wonder why create a new glass pane every time the user clicks the mouse; that wouldn't be very performant; it is probably wiser to create and attach a glass pane up front and then change its content during mouse click).
Now, regarding "painting on the glass pane", it depends on what you mean by "painting", if this means using a "Graphics" instance to directly draw on the glass pane, the answer is NO (well, actually you could but, your painting would disappear at first UI refresh...)
Such painting must occur in paintComponent() method of your glass pane (that you must override).