So I've been working on a program and I wanted to make it borderless with jframe.setUndecorated(true);. However, I can't really move the JFrame window around the screen. Is there a way I can fix that?
Here is my current code for the JFrame:
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(700, 450);
frame.setLocationRelativeTo(null);
frame.setUndecorated(true);
frame.getContentPane().setBackground(Color.BLACK);
To move the JFrame, left-click inside the JFrame somewhere, drag the mouse to the new position, and release the mouse button when the JFrame is in the correct position.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MoveUndecoratedJFrame implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new MoveUndecoratedJFrame());
}
private JFrame frame;
#Override
public void run() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setUndecorated(true);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new FlowLayout());
MoveListener listener = new MoveListener();
panel.addMouseListener(listener);
panel.addMouseMotionListener(listener);
panel.setBackground(Color.BLACK);
panel.setPreferredSize(new Dimension(700, 400));
return panel;
}
public class MoveListener implements MouseListener, MouseMotionListener {
private Point pressedPoint;
private Rectangle frameBounds;
#Override
public void mouseClicked(MouseEvent event) {
}
#Override
public void mousePressed(MouseEvent event) {
this.frameBounds = frame.getBounds();
this.pressedPoint = event.getPoint();
}
#Override
public void mouseReleased(MouseEvent event) {
moveJFrame(event);
}
#Override
public void mouseEntered(MouseEvent event) {
}
#Override
public void mouseExited(MouseEvent event) {
}
#Override
public void mouseDragged(MouseEvent event) {
moveJFrame(event);
}
#Override
public void mouseMoved(MouseEvent event) {
}
private void moveJFrame(MouseEvent event) {
Point endPoint = event.getPoint();
int xDiff = endPoint.x - pressedPoint.x;
int yDiff = endPoint.y - pressedPoint.y;
frameBounds.x += xDiff;
frameBounds.y += yDiff;
frame.setBounds(frameBounds);
}
}
}
Related
I did this little test:(stripped out all that isn't related to the problem)
package de.poller.StorrageBox;
import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainClass implements KeyListener {
JFrame frame;
JPanel panel1;
JPanel panel2;
public static void main(String[] args) {
MainClass c=new MainClass();
}
public MainClass() {
frame=new JFrame("test");
frame.setSize(new Dimension(500, 500));
frame.addKeyListener(this);
panel1=new JPanel();
JButton butt1=new JButton("test1111");
panel1.add(butt1);
panel2=new JPanel();
JButton butt2=new JButton("test222");
panel2.add(butt2);
frame.add(panel1);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.requestFocus();
}
#Override
public void keyPressed(KeyEvent arg0) {
if(arg0.getKeyChar()=='a') {
activate1();
val();
}
if(arg0.getKeyChar()=='b') {
activate2();
val();
}
}
private void activate2() {
frame.remove(panel1);
frame.add(panel2);
}
private void activate1() {
frame.remove(panel2);
frame.add(panel1);
}
private void val() {
frame.revalidate();
frame.requestFocus();
}
public void keyReleased(KeyEvent arg0) {}
public void keyTyped(KeyEvent arg0) {}
}
The first change from panel 1 to 2 is ok, but if I switch back to 1 it takes a pretty long time(more time than I want the user to have wait) and this is only a panel with 1 single button. No full gui that is planned.
The question here is: is the re-validating (I think it's this process) so slow or am I doing something horribly wrong?
Thanks to ControllAltDel the solution:
(CardLayout)
package de.poller.StorrageBox;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainClass implements KeyListener {
JFrame frame;
JPanel panel;
JPanel panel1;
JPanel panel2;
public static void main(String[] args) {
MainClass c=new MainClass();
}
public MainClass() {
frame=new JFrame("test");
frame.setSize(new Dimension(500, 500));
frame.addKeyListener(this);
panel=new JPanel(new CardLayout());
frame.add(panel);
panel1=new JPanel();
JButton butt1=new JButton("test1111");
panel1.add(butt1);
panel2=new JPanel();
JButton butt2=new JButton("test222");
panel2.add(butt2);
panel.add(panel1,"1");
panel.add(panel2,"2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.requestFocus();
}
public void keyPressed(KeyEvent arg0) {
if(arg0.getKeyChar()=='a') {
activate1();
}
if(arg0.getKeyChar()=='b') {
activate2();
}
}
private void activate2() {
CardLayout cl=(CardLayout)(panel.getLayout());
cl.show(panel, "2");
}
private void activate1() {
CardLayout cl=(CardLayout)(panel.getLayout());
cl.show(panel, "1");
}
public void keyReleased(KeyEvent arg0) {}
public void keyTyped(KeyEvent arg0) {}
}
I've a main frame on which there is a side panel with some buttons, and central panel used to display the tables and data generated from buttons on the side panel and its sub-panels
On the start my central panel is blank and I want it to always return to its initial state( blank ) after each click on a button before generating any data
I've use some sort of observer pattern (I'm not so experienced) but my problem is that the central panel must display data after clicks on some buttons that are on panels that also need a click on the side panel before to be generated
I've tried to make an executable example on the following classes, my real application displays some tables on the central panel and i send the models via the update method of the observers
hope its clear for you and I hope if you can really help me
1 - the main frame:
package tests;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MainFrame extends JFrame implements MyObserver{
private SidePanel sidePanel;
private JPanel centralPanel;
private JFrame frame;
private JLabel title;
public MainFrame(){
frame = new JFrame("TEST");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLayout(new BorderLayout());
sidePanel = new SidePanel();
sidePanel.addObserver(this);
centralPanel = new JPanel();
title = new JLabel();
initialise(0);
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
private void initialise(int i) {
if( i == 0){
centralPanel.setPreferredSize(new Dimension(400,300));
centralPanel.setBackground(Color.green);
title.setText("GREEN");
centralPanel.add(title, BorderLayout.CENTER);
frame.add(sidePanel, BorderLayout.WEST);
frame.add(centralPanel, BorderLayout.CENTER);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new MainFrame();
}
});
}
#Override
public void update(int color) {
if(color == 0){
centralPanel.setBackground(Color.yellow);
title.setText("YELLOW");
}else{
centralPanel.setBackground(Color.pink);
title.setText("PINK");
}
}
}
2 - The side Panel
package tests;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
public class SidePanel extends JPanel implements MyObserver,MyObservable{
private JPanel panel;
private JButton test;
private MyObserver observer;
private ButtonPanel buttonPanel;
public SidePanel(){
panel = new JPanel();
panel.setPreferredSize(new Dimension(140, 300));
panel.setBackground(Color.blue);
panel.setLayout(new BoxLayout(panel, 0));
test = new JButton("Lunch buttons");
test.setPreferredSize(new Dimension(80,30));
buttonPanel = new ButtonPanel();
buttonPanel.addObserver(this);
test.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
buttonPanel.setVisible(true);
}
});
panel.add(Box.createVerticalGlue());
panel.add(test);
panel.add(Box.createVerticalGlue());
panel.setVisible(true);
this.add(panel, BorderLayout.CENTER);
}
#Override
public void addObserver(MyObserver obs) {
this.observer = obs;
}
#Override
public void updateObserver(MyObserver obs, int color) {
obs.update(color);
}
#Override
public void update(int color) {
updateObserver(observer, color);
}
}
3 - the buttons panel, generally the source of any data to be displayed on the central panel
package tests;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
public class ButtonPanel extends JDialog implements MyObservable{
private JButton yellow;
private JButton orange;
private JPanel panel;
private MyObserver observer;
public ButtonPanel(){
panel = new JPanel();
panel.setPreferredSize(new Dimension(300, 40));
panel.setLayout(new FlowLayout());
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
this.setContentPane(panel);
yellow = new JButton("YELLOW");
yellow.setPreferredSize(new Dimension(100,30));
yellow.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
updateObserver(observer, 0);
}
});
orange = new JButton("ORANGE");
orange.setPreferredSize(new Dimension(100,30));
orange.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
updateObserver(observer, 1);
}
});
panel.add(yellow);
panel.add(orange);
pack();
setLocationRelativeTo(null);
}
#Override
public void addObserver(MyObserver obs) {
this.observer = obs;
}
#Override
public void updateObserver(MyObserver obs, int color) {
obs.update(color);
}
}
Finally, the customized observer and observable interfaces, note in the real app i use a table model not just an int - I'm not sure it's a good way -
package tests;
public interface MyObservable {
public void addObserver(MyObserver obs);
public void updateObserver(MyObserver obs, int color);
}
package tests;
public interface MyObserver {
public void update(int color);
}
CHANGED ANSWER:
In SidePanel.java add:
private MainFrame frame;
Then make your constructor take a MyFrame object as parameter. Do this:
public SidePanel(MainFrame frame){
this.frame = frame;
//rest not changed
//
}
Change the actionPerformed() of test button to:
test.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
buttonPanel.setVisible(true);
frame.initialise(0); // this line is added
}
});
In MainFrame.java:
Change sidePanel = new SidePanel(); to sidePanel = new SidePanel(this);
AND
Change private void initialise(int i) to public void initialise(int i)
This does what you are trying to achieve.
I am using logic like the following with a touch interface, so I'd like to be able to use mousePressed to initiate a drag, yet at the same time be able to use mouseClicked or mouseReleased if the user does not drag.
On mousePressed, I have a drag being started. On mouseClicked, I want it to print out "mouseClicked", and to print mouseReleased on "mouseReleased" but for some reason the
dropLabel.getTransferHandler().exportAsDrag(dropLabel, e,
TransferHandler.COPY);
swallows the event causing mouseClicked and mouseReleased events not be fired even when I don't move the mouse. Notice that commenting out that line causes all listeners to be fired (but obviously the drag isn't started).
How can I get all mouse events to happen the way I want, specifically mouseClicked/mouseReleased when the user doesn't do any dragging, while still being able to exportAsDragged if the user does drag? Any hacks/cracks/reflection solutions are welcome.
Here is some sample code I am working with that illustrates my actual problem:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.TransferHandler;
public class DragTest extends JFrame implements MouseMotionListener,
MouseListener {
private JPanel leftPanel = new JPanel(null);
private JPanel rightPanel = new JPanel(null);
JLabel dropLabel;
public DragTest() {
this.setLayout(new GridLayout(1, 2));
leftPanel.setBorder(BorderFactory.createLineBorder(Color.black));
rightPanel.setBorder(BorderFactory.createLineBorder(Color.black));
this.add(leftPanel);
this.add(rightPanel);
leftPanel.addMouseListener(this);
leftPanel.addMouseMotionListener(this);
JTextArea area = new JTextArea();
rightPanel.setLayout(new GridLayout(1, 1));
rightPanel.add(area);
dropLabel = new JLabel("drop");
dropLabel.setTransferHandler(new TransferHandler("text"));
}
#Override
public void mousePressed(MouseEvent e) {
System.out.println("mousePressed");
Dimension labelSize = dropLabel.getPreferredSize();
dropLabel.setSize(labelSize);
int x = e.getX() - labelSize.width / 2;
int y = e.getY() - labelSize.height / 2;
dropLabel.setLocation(x, y);
leftPanel.add(dropLabel);
dropLabel.getTransferHandler().exportAsDrag(dropLabel, e,
TransferHandler.COPY);
repaint();
}
#Override
public void mouseDragged(MouseEvent me) {
System.out.println("mouseDragged");
}
#Override
public void mouseMoved(MouseEvent e) {
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("mouseClicked");
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println("mouseReleased");
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
public static void main(String[] args) {
DragTest frame = new DragTest();
frame.setVisible(true);
frame.setSize(600, 400);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Do you really need the mouseReleased to fire or what? I think this should work well:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.TransferHandler;
public class DragTest extends JFrame implements MouseMotionListener,
MouseListener {
private JPanel leftPanel = new JPanel(null);
private JPanel rightPanel = new JPanel(null);
JLabel dropLabel;
public DragTest() {
this.setLayout(new GridLayout(1, 2));
leftPanel.setBorder(BorderFactory.createLineBorder(Color.black));
rightPanel.setBorder(BorderFactory.createLineBorder(Color.black));
this.add(leftPanel);
this.add(rightPanel);
leftPanel.addMouseListener(this);
leftPanel.addMouseMotionListener(this);
JTextArea area = new JTextArea();
rightPanel.setLayout(new GridLayout(1, 1));
rightPanel.add(area);
dropLabel = new JLabel("drop");
dropLabel.setTransferHandler(new TransferHandler("text"));
}
#Override
public void mousePressed(MouseEvent e) {
System.out.println("mousePressed");
Dimension labelSize = dropLabel.getPreferredSize();
dropLabel.setSize(labelSize);
int x = e.getX() - labelSize.width / 2;
int y = e.getY() - labelSize.height / 2;
dropLabel.setLocation(x, y);
leftPanel.add(dropLabel);
repaint();
}
#Override
public void mouseDragged(MouseEvent me) {
System.out.println("mouseDragged");
dropLabel.getTransferHandler().exportAsDrag(dropLabel, me,
TransferHandler.COPY);
}
#Override
public void mouseMoved(MouseEvent e) {
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("mouseClicked");
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println("mouseReleased");
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
public static void main(String[] args) {
DragTest frame = new DragTest();
frame.setVisible(true);
frame.setSize(600, 400);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I just moved the call to start the drag event into the mouseDragged call, this way if you just click your mouse then everything calls normally. However, if you drag the mouse, it will fire the drag and drop call, which still does block other calls, but again only if you drag. If you just click, it all fires normally.
#Override
public void mouseDragged(MouseEvent e) {
System.out.println(String.format("[mouseDragged] (%d, %d)", e.getX(),e.getY()));
Dimension labelSize = dropLabel.getPreferredSize();
dropLabel.setSize(labelSize);
int x = e.getX() - labelSize.width / 2;
int y = e.getY() - labelSize.height / 2;
dropLabel.setLocation(x, y);
leftPanel.add(dropLabel);
repaint();
}
Mouse Event..??
I have three buttons close,min and max.
When i want to max it then it will take the shape of the main container and overlaps all the panel and when i close it then only that panel gets affected. But when i hit the min button it gets minimized to the task bar which i do not want.
I want it inside conatiner like that of internalFrame when you click the minimize the button then it gets minimized inside the main frame.
here is the code
package Project;
import java.awt.Color;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
public class MinPanel {
public MinPanel() {
createAndShowGui();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new MinPanel();
}
});
}
private void createAndShowGui() {
JFrame frame = new JFrame();
frame.setSize(300, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel mainPanel = new JPanel(new GridLayout(2, 2));
for (int i = 0; i < 4; i++) {
final int num = i;
OmniPanel op = new OmniPanel(mainPanel, frame) {
#Override
public JPanel createPanel() {
JPanel p = createSimplePanelInterface();
p.add(new JLabel("Panel " + (num + 1)));
return p;
}
#Override
void toPanel() {
super.toPanel();
System.out.println("Frame requested to be brought to panel");
}
};
mainPanel.add(op.getPanel());
}
frame.add(mainPanel);
//frame.pack();
frame.setVisible(true);
}
}
abstract class OmniPanel {
protected JFrame frame;
protected JPanel panel;
boolean maximized = false;
private final JComponent owner;
private final JFrame ownerFrame;
public OmniPanel(JComponent owner, JFrame con) {
this.owner = owner;
initOmniPanel();
this.ownerFrame = con;
}
private void initOmniPanel() {
panel = createPanel();
createFrame();
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowDeiconified(WindowEvent we) {
super.windowDeiconified(we);
toPanel();
}
});
}
public JPanel getPanel() {
return panel;
}
public JFrame getFrame() {
return frame;
}
public boolean goFrame() {
frame.add(panel);
frame.pack();
frame.setState(JFrame.ICONIFIED);
frame.setVisible(true);
return true;
}
protected void createFrame() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
void toPanel() {
frame.remove(panel);
frame.dispose();
owner.add(panel);
owner.revalidate();
owner.repaint();
}
public JPanel createSimplePanelInterface() {
JPanel p = new JPanel();
JButton close = new JButton("X");
JButton minimize = new JButton("_");
JButton maximize = new JButton("[]");
p.add(close);
p.add(minimize);
p.add(maximize);
close.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
if (maximized) {
maximized = false;
ownerFrame.setGlassPane(new JComponent() {
});
ownerFrame.revalidate();
ownerFrame.repaint();
} else {
removePanelFromOwner();
getFrame().dispose();
}
}
});
minimize.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
if (maximized) {
maximized = false;
ownerFrame.setGlassPane(new JComponent() {
});
owner.add(panel);
owner.revalidate();
owner.repaint();
ownerFrame.revalidate();
ownerFrame.repaint();
} else {
removePanelFromOwner();
goFrame();
frame.setState(Frame.ICONIFIED);
}
}
});
maximize.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
if (maximized) {
return;
}
maximized = true;
removePanelFromOwner();
ownerFrame.setGlassPane(panel);
ownerFrame.revalidate();
ownerFrame.repaint();
panel.setVisible(true);//
}
});
p.setBorder(new LineBorder(Color.black));
return p;
}
private void removePanelFromOwner() {
owner.remove(getPanel());
owner.revalidate();
owner.repaint();
}
abstract JPanel createPanel();
}
I would suggest you to create an internalframe and then add buttons.If you do not want to add buttons then you make internalframe arguments true
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
import javax.swing.plaf.basic.BasicInternalFrameUI;
public class MinPanel {
public MinPanel() throws HeadlessException, PropertyVetoException {
createAndShowGUI();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new MinPanel();
} catch (HeadlessException ex) {
} catch (PropertyVetoException ex) {
}
}
});
}
private void createAndShowGUI() throws HeadlessException, PropertyVetoException {
JFrame frame = new JFrame();
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
final JDesktopPane jdp = new JDesktopPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
};
frame.setContentPane(jdp);
frame.pack();
createAndAddInternalFrame(jdp, 0, 0);
createAndAddInternalFrame(jdp, 200, 0);
frame.setVisible(true);
}
private void createAndAddInternalFrame(final JDesktopPane jdp, int x, int y) throws PropertyVetoException {
final JInternalFrame jInternalFrame = new JInternalFrame("Test1", false, false, false, false);
jInternalFrame.setLocation(x, y);
jInternalFrame.setLayout(new GridLayout(2, 2));
jInternalFrame.setSize(200, 200);//testing
JButton jb = new JButton("min");
jInternalFrame.add(jb);
jb.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
try {
jInternalFrame.setIcon(true);
} catch (PropertyVetoException ex) {
}
}
});
BasicInternalFrameTitlePane titlePane = (BasicInternalFrameTitlePane) ((BasicInternalFrameUI) jInternalFrame.getUI()).getNorthPane();
jInternalFrame.remove(titlePane);
jInternalFrame.setVisible(true);
jdp.add(jInternalFrame);
}
}
I've made a custom subclass of JLabel. I have a single instance of this, inside a single JPanel, inside a single JFrame. I do not override the paintComponent() method; all the class does is change the background color when the cursor hovers over it.
The JFrame loads immediately, but for several seconds the JPanel is left undrawn. I verified that this is because of my custom class by overriding paintComponent() and adding some debug println() statements.
public void paintComponent(Graphics context)
{
System.out.println("Painting...");
super.paintComponent(context);
System.out.println("Painted.");
}
The strange thing is, it's drawn instantly when I use Panel instead of JPanel or Label instead of JLabel.
Where is this lag coming from?
EDIT: Some example code. Nothing is actually drawn; look at the console message delay.
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.GridLayout;
import javax.swing.JPanel;
public class Example extends JLabel implements MouseListener
{
private static final long serialVersionUID = 0;
public Example()
{
super();
System.out.println("Constructed.");
}
public void paintComponent(java.awt.Graphics g)
{
System.out.println("Painting component...");
super.paintComponent(g);
System.out.println("Painted.");
}
public void mouseEntered(MouseEvent event) { }
public void mouseExited(MouseEvent event) { }
public void mouseReleased(MouseEvent event) { }
public void mousePressed(MouseEvent event) { }
public void mouseClicked(MouseEvent event) { }
public static void main(final String[] arguments)
{
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1, 1));
panel.add(new Example());
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setVisible(true);
System.out.println("Set visible.");
}
}
My code doesn't lag:
My SSCCE:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class LabelTest extends JPanel {
public LabelTest() {
add(new MyLabel("Fubar!"));
}
private static void createAndShowGui() {
LabelTest mainPanel = new LabelTest();
JFrame frame = new JFrame("LabelTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class MyLabel extends JLabel {
private static final Color BACKGROUND_DEFAULT = new Color(200, 200, 255);
private static final Color BACKGROUND_MOUSEOVER = new Color(255, 200, 200);
private static final int PREF_W = 200;
private static final int PREF_H = 100;
public MyLabel(String text) {
super(text, SwingConstants.CENTER);
setOpaque(true);
setBackground(BACKGROUND_DEFAULT);
addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent arg0) {
setBackground(BACKGROUND_MOUSEOVER);
}
#Override
public void mouseExited(MouseEvent e) {
setBackground(BACKGROUND_DEFAULT);
}
});
}
#Override
public Dimension getPreferredSize() {
int width = Math.max(super.getPreferredSize().width, PREF_W);
int height = Math.max(super.getPreferredSize().height, PREF_H);
return new Dimension(width, height);
}
}
This suggests to me that the problem isn't in the concept of a JLabel whose background changes via a MouseListener, but rather you've got a bug somewhere in your code. Where? Who knows until you post compilable runnable code, an SSCCE, like the one I've posted above.