954,549 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Moving JPanels

Hello,

I'm trying to make a JPanel with JFrame capabilities,
such as resizing, and moving, Everything seems to work fine,
altough there are minor flickering inside the JPanel,
I have numeral repaints and I have a method called update(), which uses absolute position to arrange Containers and Components.
Whenever the JPanel is resized, update() is called.

This is a 2 part problem.

1. Flickering.
2. Cant get a container from another class to get resized within the JPanel.

Is there any way to resolve these problems?

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

public class sys_windows extends JPanel 
			implements ActionListener, MouseMotionListener, MouseListener
{
	private JPanel titlebar, titlepane;
	public  JPanel content;
	private JLabel title;
	private int xPos, yPos, prevX, prevY = 0;
	private int xSize, ySize = 0;
	public JButton[] btn = new JButton[3];
	
	
	public Container container; public Component comp;
	
	public sys_windows()
	{
		titlebar = new JPanel();
		titlebar.setLayout(null);
		titlebar.setBackground(new Color(255,255,255, 10));
		titlebar.addMouseListener(this);
		titlebar.addMouseMotionListener(this);
		titlebar.setDoubleBuffered(true);
		titlebar.setOpaque(true);
		titlebar.setVisible(true);
		
		titlepane = new JPanel();
		titlepane.setLayout(null);
		titlepane.setBackground(new Color(255,255,255, 0));
		titlepane.setDoubleBuffered(true);
		titlepane.setOpaque(true);
		titlepane.setVisible(true);
		
		content = new JPanel();
		content.setLayout(new BorderLayout());
		content.setBackground(Color.WHITE);
		content.setBorder(BorderFactory.createEtchedBorder());
		content.addMouseListener(this);
		content.addMouseMotionListener(this);
		content.setDoubleBuffered(true);
		content.setOpaque(true);
		content.setVisible(true);
		
		for (int i=0; i<btn.length; i++)
		{
			btn[i] = new JButton();
			btn[i].setDoubleBuffered(true);
			btn[i].addActionListener(this);
			btn[i].setOpaque(false);
			btn[i].setBackground(new Color(0,80,130, 40));
			btn[i].setForeground(Color.WHITE);
			btn[i].setFont(new Font("SansSerif", Font.BOLD, 12));
			btn[i].setBorderPainted(true);
			btn[i].setContentAreaFilled(true);
			btn[i].setVisible(true);
		}
		
		title = new JLabel("", JLabel.LEFT);
		title.setForeground(Color.BLACK);
		title.setDoubleBuffered(true);
		
		btn[0].setText("x");
		btn[1].setText("+");
		btn[2].setText("--");
		
		setLayout(null);
		setBackground(new Color(255,255,255, 50));
		setBorder(BorderFactory.createEtchedBorder());
		addMouseListener(this);
		addMouseMotionListener(this);
		setSize(200,200);
		setOpaque(true);
		setVisible(true);
		
		update();
	}
	
	public void addComponent(Container container,
		Component c, int x, int y, int width, int height)
	{
		c.setBounds(x,y,width,height);
		container.add(c);
	}
	
	public void setContent(Container container)
	{
		this.container.add(container);
		repaint();
		update();
	}
	
	public void update()
	{
		addComponent(this, content,  5,30, getWidth()-10, getHeight()-35);
		addComponent(titlepane, title, 5, 1, getWidth(), 30);
		addComponent(titlebar, titlepane, 0, 0, getWidth()-120, 30);
		addComponent(this, titlebar, 0,0, getWidth(), 30);
		addComponent(titlebar, btn[0], titlebar.getWidth()-btn[0].getWidth(), 2,45,20);
		addComponent(titlebar, btn[1], titlebar.getWidth()-btn[1].getWidth()-btn[0].getWidth(),2,38,20);
		addComponent(titlebar, btn[2], titlebar.getWidth()-btn[2].getWidth()-btn[1].getWidth()-btn[0].getWidth(), 2, 38, 20);

		repaint();
	}
	
	public void setTitle(String title)
	{
		this.title.setText(title);
	}
	
	
	public void actionPerformed(ActionEvent e)
	{
		if (e.getSource() == btn[0])
		{
			setVisible(false);
			setEnabled(false);
			Runtime.getRuntime().gc();
		}
		
		if (e.getSource() == btn[1])
		{
			
		}
		
		if (e.getSource() == btn[2])
		{
			setVisible(true);
		}
	}
	
	public void mouseDragged(MouseEvent e)
	{
		if (e.getSource() == this)
		{
			xSize = e.getX();
			ySize = e.getY();

			if (xSize < 120)
			{
				xSize = 120;
			}
			
			if (ySize < 40)
			{
				ySize = 40;
			}
			setSize(xSize, ySize);
			repaint();
			update();
		}
		
		if (e.getSource() == titlebar)
		{
			xPos = this.getX() + e.getXOnScreen() - prevX;
			yPos = this.getY() + e.getYOnScreen() - prevY;
			
			setLocation(xPos, yPos);
			repaint();
			
			prevX = e.getXOnScreen();
			prevY = e.getYOnScreen();
		}
	}
	
	public void mousePressed(MouseEvent e)
	{
		prevX = e.getXOnScreen();
		prevY = e.getYOnScreen();
		repaint();
	}
	
	public void mouseClicked(MouseEvent e)
	{

	}
	
	public void mouseReleased(MouseEvent e)
	{
	}
	
	public void mouseMoved(MouseEvent e)
	{
		
	}
	
	public void mouseEntered(MouseEvent e)
	{
		
	}
	
	public void mouseExited(MouseEvent e)
	{
		
	}
}
117
Light Poster
45 posts since Jan 2012
Reputation Points: 10
Solved Threads: 2
 

1) learn for Naming Conventions

2) don't use AbsoluteLayout for dynaminc container, I saw a few simialir code, but you have to add ComponentListener delayed by Swing Timer , that reduce caused flickering

mKorbel
Veteran Poster
1,141 posts since Feb 2011
Reputation Points: 480
Solved Threads: 224
 

1) learn for Naming Conventions

2) don't use AbsoluteLayout for dynaminc container, I saw a few simialir code, but you have to add ComponentListener delayed by Swing Timer , that reduce caused flickering


Thanks for the answer,
but it's not really the flickering that bothers me the most.
The biggest problem I have right now is to add a Container (JPanel), from another class
and get it resized when the Main JPanel is resized.


What comes to the absolute positioning part, everything seems to work fine because the specified x,y variables are dynamic instead of the method.
Altough I guess there are numeral ways to do the exact same thing with another Layout,
If so, do you have any suggestions?

117
Light Poster
45 posts since Jan 2012
Reputation Points: 10
Solved Threads: 2
 

Thanks for the answer, but it's not really the flickering that bothers me the most. The biggest problem I have right now is to add a Container (JPanel), from another class and get it resized when the Main JPanel is resized.

What comes to the absolute positioning part, everything seems to work fine because the specified x,y variables are dynamic instead of the method. Altough I guess there are numeral ways to do the exact same thing with another Layout, If so, do you have any suggestions?


Hmm may this : http://www.coderanch.com/t/341559/GUI/java/resize-JPanel-size-JFrame-size also have you tried using revalidate()? but mostly the searches have been saying change your setSize into setPreferredSize(new Dimension(int length, int width)) and maybe use of them in conjunction might prove fruitful? not sure though

DavidKroukamp
Practically a Master Poster
Team Colleague
693 posts since Dec 2011
Reputation Points: 282
Solved Threads: 169
 

my questions are

1) are want to really moving with JComponent inside Container , is pretty possible and nothing special

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

public class Demo implements MouseListener, MouseMotionListener {

    private int startDragX, startDragY;
    private boolean inDrag = false;
    private JLabel sprite = new JLabel("drag me");

    public Demo() {
        JFrame frame = new JFrame("drag demo");
        frame.setLayout(null);
        frame.setMinimumSize(new Dimension(400, 300));
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        sprite.setBounds(10, 10, 80, 20);
        sprite.addMouseListener(this);
        sprite.addMouseMotionListener(this);
        frame.add(sprite);

        frame.setVisible(true);
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // not interested
    }

    @Override
    public void mouseExited(MouseEvent e) {
        // not interested
    }

    @Override
    public void mousePressed(MouseEvent e) {
        startDragX = e.getX();
        startDragY = e.getY();
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (inDrag) {
            System.out.println("Sprite dragged to " + sprite.getX() + ", " + sprite.getY());
            inDrag = false;
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        // not interested
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        int newX = sprite.getX() + (e.getX() - startDragX);
        int newY = sprite.getY() + (e.getY() - startDragY);
        sprite.setLocation(newX, newY);
        inDrag = true;
    }

    @Override
    public void mouseMoved(MouseEvent arg0) {
        // not interested
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                Demo demo = new Demo();
            }
        });
    }
}

2) do you able to see that class from this code

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

public class Demo {

    public Demo() {
        JFrame frame = new JFrame("drag demo");
        frame.setMinimumSize(new Dimension(400, 300));
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Sys_Windows sprite = new Sys_Windows();
        frame.add(sprite);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                Demo demo = new Demo();
            }
        });
    }
}
mKorbel
Veteran Poster
1,141 posts since Feb 2011
Reputation Points: 480
Solved Threads: 224
 

I combined both of your answers, and managed to get it to work.
Revalidating fixed the issue with the other containers size.
The ComponentListener saved me a lot of time and coding.

Only flickering remains.
Is there perhaps a simpler way to resolve this, without the Swing Timer?
The ComponentListener is still effecient, Any advice?

Thank for all help.

117
Light Poster
45 posts since Jan 2012
Reputation Points: 10
Solved Threads: 2
 

Is there a reason not to just use JInternalFrames for this? It seems that is what you're trying to mimic.

Ezzaral
Posting Genius
Moderator
15,986 posts since May 2007
Reputation Points: 3,250
Solved Threads: 847
 

Found out that the problem lies in the main class.
I had a javax.swing.Timer which were repainting every 100 millisecond, which
resulted in flickering when resized.

This probably means that none of my repaint methods inside the window JPanel worked.

Is there any way to repaint in the main class from another class?
Else: Is there any way to repaint the class component(Container) so it's visible
trough the main class, (Maybe without a javax.swing.Timer)?

117
Light Poster
45 posts since Jan 2012
Reputation Points: 10
Solved Threads: 2
 

Swing Timer is correct way, but you have to determine if resize ended or continue, for this reason is there required to make a delay invoked by Swing Timer

mKorbel
Veteran Poster
1,141 posts since Feb 2011
Reputation Points: 480
Solved Threads: 224
 
Swing Timer is correct way, but you have to determine if resize ended or continue, for this reason is there required to make a delay invoked by Swing Timer

It seems that the visual repaint is done in the main class.
Any repaint in the panel class doesn't seem to take effect.
Therefor I don't know where to place the timer, except for the main class.
So I need to repaint from the main class, then shouldn't the indrag boolean be public?

I tried changing the opacity of the panel to fully opaque, I then noticed that no flickering occured during resize,
probably because the panel was opaque.
When I changed it back to

setBackground(new Color(255,255,255, 50));


it became transparent and then (the flicker)
which looks like trails of the panels size history inside the panel, started again.

If the timer is placed with an ActionListener inside the panel class, it will call repaint() -
when boolean is true.
The odd thing is that whenever the panel-class is moved on the screen (not resized) the
repainting of the class seems to work.


Thanks for all the useful help and information.

117
Light Poster
45 posts since Jan 2012
Reputation Points: 10
Solved Threads: 2
 

I have figured out that, whenever I use a background image
the repaint works properly, but whenever I use the current background panel color
the windows flicker, or doesn't properly repaint.

Is there any known way in order to fix this?

117
Light Poster
45 posts since Jan 2012
Reputation Points: 10
Solved Threads: 2
 

Bump...

117
Light Poster
45 posts since Jan 2012
Reputation Points: 10
Solved Threads: 2
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: