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)
	{
		
	}
}

Recommended Answers

All 11 Replies

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?

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

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();
            }
        });
    }
}

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.

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)?

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

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.

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?

Bump...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.