Problem: An undecorated JFrame with a transparent background flickers when using a ComponentResizer to resize it. As seen in the below video and MCVE, the problem does not occur with an opaque background.
ComponentResizer (A MouseAdapter) works by calculating the drag distance and direction when the mouse is dragged and changes the size of its component accordingly.
The answer to What causes the Jframe to flicker while resizing? links to How to stop the auto-repaint() when I resize the Jframe, which says to turn of dynamic layout with Toolkit.getDefaultToolkit().setDynamicLayout(false), however, this does not solve the problem as it has no effect, possibly because macOS is not a platform that allows it to be disabled.
Question: How can I allow the user to resize an undecorated JFrame with a transparent background without it flickering? Is ComponentResizer the problem?
MCVE: (Length due to ComponentResizer class)
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.Map;
public class JFrameFlickerMCVE {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
Toolkit.getDefaultToolkit().setDynamicLayout(false);
final JFrame frame = new JFrame();
frame.setUndecorated(true);
final JToggleButton backgroundButton = new JToggleButton("Break me!");
backgroundButton.setSelected(true);
backgroundButton.addActionListener(e -> {
if(!backgroundButton.isSelected()) {
frame.setBackground(new Color(0, 0, 0, 0));
backgroundButton.setText("Fix me!");
} else {
frame.setBackground(UIManager.getColor("control"));
backgroundButton.setText("Break me!");
}
});
final JLabel label = new JLabel("Resize Here");
label.setBorder(BorderFactory.createLineBorder(Color.RED));
frame.getContentPane().add(backgroundButton);
frame.getContentPane().add(label, BorderLayout.SOUTH);
new ComponentResizer(frame);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
/**
* The ComponentResizer allows you to resize a component by dragging a border
* of the component.
*/
public static class ComponentResizer extends MouseAdapter
{
private final static Dimension MINIMUM_SIZE = new Dimension(10, 10);
private final static Dimension MAXIMUM_SIZE =
new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
private static Map<Integer, Integer> cursors = new HashMap<Integer, Integer>();
{
cursors.put(1, Cursor.N_RESIZE_CURSOR);
cursors.put(2, Cursor.W_RESIZE_CURSOR);
cursors.put(4, Cursor.S_RESIZE_CURSOR);
cursors.put(8, Cursor.E_RESIZE_CURSOR);
cursors.put(3, Cursor.NW_RESIZE_CURSOR);
cursors.put(9, Cursor.NE_RESIZE_CURSOR);
cursors.put(6, Cursor.SW_RESIZE_CURSOR);
cursors.put(12, Cursor.SE_RESIZE_CURSOR);
}
private Insets dragInsets;
private Dimension snapSize;
private int direction;
protected static final int NORTH = 1;
protected static final int WEST = 2;
protected static final int SOUTH = 4;
protected static final int EAST = 8;
private Cursor sourceCursor;
private boolean resizing;
private Rectangle bounds;
private Point pressed;
private boolean autoscrolls;
private Dimension minimumSize = MINIMUM_SIZE;
private Dimension maximumSize = MAXIMUM_SIZE;
/**
* Convenience contructor. All borders are resizable in increments of
* a single pixel. Components must be registered separately.
*/
public ComponentResizer()
{
this(new Insets(5, 5, 5, 5), new Dimension(1, 1));
}
/**
* Convenience contructor. All borders are resizable in increments of
* a single pixel. Components can be registered when the class is created
* or they can be registered separately afterwards.
*
* #param components components to be automatically registered
*/
public ComponentResizer(Component... components)
{
this(new Insets(5, 5, 5, 5), new Dimension(1, 1), components);
}
/**
* Convenience contructor. Eligible borders are resisable in increments of
* a single pixel. Components can be registered when the class is created
* or they can be registered separately afterwards.
*
* #param dragInsets Insets specifying which borders are eligible to be
* resized.
* #param components components to be automatically registered
*/
public ComponentResizer(Insets dragInsets, Component... components)
{
this(dragInsets, new Dimension(1, 1), components);
}
/**
* Create a ComponentResizer.
*
* #param dragInsets Insets specifying which borders are eligible to be
* resized.
* #param snapSize Specify the dimension to which the border will snap to
* when being dragged. Snapping occurs at the halfway mark.
* #param components components to be automatically registered
*/
public ComponentResizer(Insets dragInsets, Dimension snapSize, Component... components)
{
setDragInsets( dragInsets );
setSnapSize( snapSize );
registerComponent( components );
}
/**
* Get the drag insets
*
* #return the drag insets
*/
public Insets getDragInsets()
{
return dragInsets;
}
/**
* Set the drag dragInsets. The insets specify an area where mouseDragged
* events are recognized from the edge of the border inwards. A value of
* 0 for any size will imply that the border is not resizable. Otherwise
* the appropriate drag cursor will appear when the mouse is inside the
* resizable border area.
*
* #param dragInsets Insets to control which borders are resizeable.
*/
public void setDragInsets(Insets dragInsets)
{
validateMinimumAndInsets(minimumSize, dragInsets);
this.dragInsets = dragInsets;
}
/**
* Get the components maximum size.
*
* #return the maximum size
*/
public Dimension getMaximumSize()
{
return maximumSize;
}
/**
* Specify the maximum size for the component. The component will still
* be constrained by the size of its parent.
*
* #param maximumSize the maximum size for a component.
*/
public void setMaximumSize(Dimension maximumSize)
{
this.maximumSize = maximumSize;
}
/**
* Get the components minimum size.
*
* #return the minimum size
*/
public Dimension getMinimumSize()
{
return minimumSize;
}
/**
* Specify the minimum size for the component. The minimum size is
* constrained by the drag insets.
*
* #param minimumSize the minimum size for a component.
*/
public void setMinimumSize(Dimension minimumSize)
{
validateMinimumAndInsets(minimumSize, dragInsets);
this.minimumSize = minimumSize;
}
/**
* Remove listeners from the specified component
*
* #param component the component the listeners are removed from
*/
public void deregisterComponent(Component... components)
{
for (Component component : components)
{
component.removeMouseListener( this );
component.removeMouseMotionListener( this );
}
}
/**
* Add the required listeners to the specified component
*
* #param component the component the listeners are added to
*/
public void registerComponent(Component... components)
{
for (Component component : components)
{
component.addMouseListener( this );
component.addMouseMotionListener( this );
}
}
/**
* Get the snap size.
*
* #return the snap size.
*/
public Dimension getSnapSize()
{
return snapSize;
}
/**
* Control how many pixels a border must be dragged before the size of
* the component is changed. The border will snap to the size once
* dragging has passed the halfway mark.
*
* #param snapSize Dimension object allows you to separately spcify a
* horizontal and vertical snap size.
*/
public void setSnapSize(Dimension snapSize)
{
this.snapSize = snapSize;
}
/**
* When the components minimum size is less than the drag insets then
* we can't determine which border should be resized so we need to
* prevent this from happening.
*/
private void validateMinimumAndInsets(Dimension minimum, Insets drag)
{
int minimumWidth = drag.left + drag.right;
int minimumHeight = drag.top + drag.bottom;
if (minimum.width < minimumWidth
|| minimum.height < minimumHeight)
{
String message = "Minimum size cannot be less than drag insets";
throw new IllegalArgumentException( message );
}
}
/**
*/
#Override
public void mouseMoved(MouseEvent e)
{
Component source = e.getComponent();
Point location = e.getPoint();
direction = 0;
if (location.x < dragInsets.left)
direction += WEST;
if (location.x > source.getWidth() - dragInsets.right - 1)
direction += EAST;
if (location.y < dragInsets.top)
direction += NORTH;
if (location.y > source.getHeight() - dragInsets.bottom - 1)
direction += SOUTH;
// Mouse is no longer over a resizable border
if (direction == 0)
{
source.setCursor( sourceCursor );
}
else // use the appropriate resizable cursor
{
int cursorType = cursors.get( direction );
Cursor cursor = Cursor.getPredefinedCursor( cursorType );
source.setCursor( cursor );
}
}
#Override
public void mouseEntered(MouseEvent e)
{
if (! resizing)
{
Component source = e.getComponent();
sourceCursor = source.getCursor();
}
}
#Override
public void mouseExited(MouseEvent e)
{
if (! resizing)
{
Component source = e.getComponent();
source.setCursor( sourceCursor );
}
}
#Override
public void mousePressed(MouseEvent e)
{
// The mouseMoved event continually updates this variable
if (direction == 0) return;
// Setup for resizing. All future dragging calculations are done based
// on the original bounds of the component and mouse pressed location.
resizing = true;
Component source = e.getComponent();
pressed = e.getPoint();
SwingUtilities.convertPointToScreen(pressed, source);
bounds = source.getBounds();
// Making sure autoscrolls is false will allow for smoother resizing
// of components
if (source instanceof JComponent)
{
JComponent jc = (JComponent)source;
autoscrolls = jc.getAutoscrolls();
jc.setAutoscrolls( false );
}
}
/**
* Restore the original state of the Component
*/
#Override
public void mouseReleased(MouseEvent e)
{
resizing = false;
Component source = e.getComponent();
source.setCursor( sourceCursor );
if (source instanceof JComponent)
{
((JComponent)source).setAutoscrolls( autoscrolls );
}
}
/**
* Resize the component ensuring location and size is within the bounds
* of the parent container and that the size is within the minimum and
* maximum constraints.
*
* All calculations are done using the bounds of the component when the
* resizing started.
*/
#Override
public void mouseDragged(MouseEvent e)
{
if (resizing == false) return;
Component source = e.getComponent();
Point dragged = e.getPoint();
SwingUtilities.convertPointToScreen(dragged, source);
changeBounds(source, direction, bounds, pressed, dragged);
}
protected void changeBounds(Component source, int direction, Rectangle bounds, Point pressed, Point current)
{
// Start with original locaton and size
int x = bounds.x;
int y = bounds.y;
int width = bounds.width;
int height = bounds.height;
// Resizing the West or North border affects the size and location
if (WEST == (direction & WEST))
{
int drag = getDragDistance(pressed.x, current.x, snapSize.width);
int maximum = Math.min(width + x, maximumSize.width);
drag = getDragBounded(drag, snapSize.width, width, minimumSize.width, maximum);
x -= drag;
width += drag;
}
if (NORTH == (direction & NORTH))
{
int drag = getDragDistance(pressed.y, current.y, snapSize.height);
int maximum = Math.min(height + y, maximumSize.height);
drag = getDragBounded(drag, snapSize.height, height, minimumSize.height, maximum);
y -= drag;
height += drag;
}
// Resizing the East or South border only affects the size
if (EAST == (direction & EAST))
{
int drag = getDragDistance(current.x, pressed.x, snapSize.width);
Dimension boundingSize = getBoundingSize( source );
int maximum = Math.min(boundingSize.width - x, maximumSize.width);
drag = getDragBounded(drag, snapSize.width, width, minimumSize.width, maximum);
width += drag;
}
if (SOUTH == (direction & SOUTH))
{
int drag = getDragDistance(current.y, pressed.y, snapSize.height);
Dimension boundingSize = getBoundingSize( source );
int maximum = Math.min(boundingSize.height - y, maximumSize.height);
drag = getDragBounded(drag, snapSize.height, height, minimumSize.height, maximum);
height += drag;
}
source.setBounds(x, y, width, height);
source.validate();
}
/*
* Determine how far the mouse has moved from where dragging started
*/
private int getDragDistance(int larger, int smaller, int snapSize)
{
int halfway = snapSize / 2;
int drag = larger - smaller;
drag += (drag < 0) ? -halfway : halfway;
drag = (drag / snapSize) * snapSize;
return drag;
}
/*
* Adjust the drag value to be within the minimum and maximum range.
*/
private int getDragBounded(int drag, int snapSize, int dimension, int minimum, int maximum)
{
while (dimension + drag < minimum)
drag += snapSize;
while (dimension + drag > maximum)
drag -= snapSize;
return drag;
}
/*
* Keep the size of the component within the bounds of its parent.
*/
private Dimension getBoundingSize(Component source)
{
if (source instanceof Window)
{
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
Rectangle bounds = env.getMaximumWindowBounds();
return new Dimension(bounds.width, bounds.height);
}
else
{
return source.getParent().getSize();
}
}
}
}
I searched for a solution but no one was working...
The reason seems to be the redrawing of all component tree during the resize user action.
As the redrawing of the resized component and of its children components is done not only after mouse released (end of the resize) but during the resize too (during mouse dragging) I tried to comment the
source.validate();
line into
changeBounds method (it is continuously called during dragging).
I put the line at the beginning of mouseReleased method into a if block:
if(resizing == true) {
e.getComponent().validate();
}
It works (the flickering is almost absent).
Let me know if this solution works for you too...
Related
I am trying to make a paintable JPanel, with optional gridline display. To do this, I have a custom JPanel, which makes another JPanel that holds just the gridlines. That way, I can show / hide the grid lines without ever removing what is on the canvas.
All seems to be working, except for some weird alignment issues I can seem to pin down. When I start drawing some squares, they are only a few pixels above the gridlines. How can I fix this so that both panels are displaying EXACTLY on top of one another?
Here is an example of the issue:
package com.carvethsolutions.guilib.customcomp;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
/**
* A custom component for displaying a grid
*/
public class GridCanvas extends JPanel implements MouseListener {
/**
* Width and height of the canvas, in pixels
*/
private int width, height;
/**
* How many pixels represent one square on the grid
*/
private int gridScale;
/**
* The separate panel that holds the grid lines
*/
private JPanel gridPanel;
private boolean gridLinesVisible = true;
/**
* Holds color selections
*/
private Paintbrush paintbrush;
public GridCanvas() {
super();
width = 500;
height = 500;
setupComponent();
}
public GridCanvas(int width, int height) {
super();
this.width = width;
this.height = height;
setupComponent();
}
/**
* Private function to prepare the component.
*/
private void setupComponent() {
gridScale = 50;
this.setPreferredSize(new Dimension(width,height));
this.setBackground(Color.WHITE);
this.addMouseListener(this);
gridPanel = new JPanel() {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Vertical Lines
for (int x = gridScale; x <= width; x += gridScale) {
g.drawLine(x, 0, x, height);
}
for (int y = gridScale; y <= height; y += gridScale) {
g.drawLine(0, y, width, y);
}
}
};
gridPanel.setVisible(gridLinesVisible);
gridPanel.setPreferredSize(this.getPreferredSize());
this.add(gridPanel);
this.setSize(gridPanel.getSize());
paintbrush = new Paintbrush(Color.black);
}
/**
* Enable or disable grid lines from appearing on the Canvas
*/
public void toggleGridlines() {
gridLinesVisible = !gridLinesVisible;
gridPanel.setVisible(gridLinesVisible);
}
/**
* Invoked when the mouse button has been clicked (pressed
* and released) on a component.
*
* #param e
*/
#Override
public void mouseClicked(MouseEvent e) {
int x = e.getX() / gridScale;
int y = e.getY() / gridScale;
System.out.println("mouseClicked Event : (" + x + ", " + y + ")");
this.getGraphics().setColor(paintbrush.getColor());
this.getGraphics().fillRect(x * gridScale, y * gridScale, gridScale, gridScale);
}
/**
* Invoked when a mouse button has been pressed on a component.
*
* #param e
*/
#Override
public void mousePressed(MouseEvent e) {
}
/**
* Invoked when a mouse button has been released on a component.
*
* #param e
*/
#Override
public void mouseReleased(MouseEvent e) {
}
/**
* Invoked when the mouse enters a component.
*
* #param e
*/
#Override
public void mouseEntered(MouseEvent e) {
}
/**
* Invoked when the mouse exits a component.
*
* #param e
*/
#Override
public void mouseExited(MouseEvent e) {
}
}
To do this, I have a custom JPanel, which makes another JPanel that holds just the gridlines. That way, I can show / hide the grid lines without ever removing what is on the canvas.
Well, that is the wrong approach. Your panel should have properties:
paint the gridlines or not
a 2D array to control which squares should be filled.
Your paint logic is wrong:
this.getGraphics().setColor(paintbrush.getColor());
this.getGraphics().fillRect(x * gridScale, y * gridScale, gridScale, gridScale);
You should never use getGraphics(...) on a component to do custom painting. The first time Swing determines the components needs to be repainted you will lose all the painting. For example if you resize the frame.
Instead. custom painting must be done in the paintComponent() of the component. Then you:
first paint the gridlines if required
iterate through the 2D array and paint any squares as required.
Read the section from the Swing tutorial on Custom Painting for more information and working examples.
Or instead of the 2D Array, use an ArrayList to contain objects to be painted. This object could simply be a Point object to control the x/y location of a square to be painted, or is could be an object that contains complete information about the object to be painted such as location/color/shape. Check out Custom Painting Approaches for a working example of this approach.
I'm coding a basic paint program and I have been having trouble with Rectangle and Ellipse tools. If you click and drag you should be able to draw the shape with the dimensions based on the startpoint and endpoint (both use getX() and getY()), the problem being that these two shapes get the startpoint right but the endpoint is offset in both the x and y coordinates.
This code below is pretty much the same as the code that I used in my line tool (which works properly) except swapping Line2D with Rectangle2D and Ellipse2D respectively.
package tools;
import gui.DrawingPanel;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
/**
* Creates the Rectangle Action.
*#version 1
*/
public class RectangleAction extends AbstractAction {
private final DrawingPanel myPanel;
private Rectangle2D.Double myRectangle;
private double Start_X;
private double Start_Y;
/**
* Constructor for Rectangle Action.
*/
public RectangleAction(final DrawingPanel thePanel) {
super("Rectangle", getImageIcon());
myPanel = thePanel;
putValue(Action.MNEMONIC_KEY, KeyEvent.VK_R);
putValue(Action.SELECTED_KEY, true);
}
#Override
public void actionPerformed(final ActionEvent theEvent) {
myPanel.addMouseListener(new MyMouseListener());
myPanel.addMouseMotionListener(new MyMouseListener());
}
/**
* gets the image icon of the action.
* #return the image icon.
*/
public static ImageIcon getImageIcon() {
return new ImageIcon("./images/rectangle.gif");
}
/**
* Listens for mouse clicks, to draw on our panel.
*/
private class MyMouseListener extends MouseAdapter {
private double myX2;
private double myY2;
/**
* Handles a click event.
*
* #param theEvent The event.
*/
#Override
public void mousePressed(final MouseEvent theEvent) {
Start_X = (double) theEvent.getX();
Start_Y = (double) theEvent.getY();
}
/**
* Handles the release event.
*
* #param theEvent The event.
*/
#Override
public void mouseReleased(final MouseEvent theEvent) {
myX2 = (double) theEvent.getX();
myY2 = (double) theEvent.getY();
myRectangle = new Rectangle2D.Double(Start_X, Start_Y, myX2, myY2);
myPanel.setShape(myRectangle);
myPanel.repaint();
}
/**
* Handles a click event.
*
* #param theEvent The event.
*/
#Override
public void mouseDragged(final MouseEvent theEvent) {
myX2 = (double) theEvent.getX();
myY2 = (double) theEvent.getY();
myRectangle = new Rectangle2D.Double(Start_X, Start_Y, myX2, myY2);
myPanel.setShape(myRectangle);
myPanel.repaint();
}
}
}
I should note that I did look at this similar question but it didn't give me the answer I was looking for; also the DrawingPanel is just a JPanel with a Paint Component to draw the shape and nothing else.
myRectangle = new Rectangle2D.Double(Start_X, Start_Y, myX2, myY2);
The parameters are (x, y, width, height) you are trying to specify two points.
Your painting logic assumes you always drag the mouse from top/left to bottom/right. It is always possible the mouse could be dragged up and left which would result in negative values when you calculate the width/height based on the two points.
This is code I have used to calculate the Rectangle bounds correctly:
int x = Math.min(startPoint.x, e.getX());
int y = Math.min(startPoint.y, e.getY());
int width = Math.abs(startPoint.x - e.getX());
int height = Math.abs(startPoint.y - e.getY());
You don't need to create two listeners, you can just share the same listener:
//myPanel.addMouseListener(new MyMouseListener());
//myPanel.addMouseMotionListener(new MyMouseListener());
MouseAdapter myMouseAdapter = new MyMouseListener();
myPanel.addMouseListener( myMouseAdapter );
myPanel.addMouseMotionListener( myMouseAdapter);
Also, you keep adding the adapter to the panel every time you click on the button. So if you click on you line tool, then the ellispse tool and then the rectangle tool you will have 3 listener added to the panel. I would suggest you should remove all listeners from the panel before adding your listener for the current tool.
You're initializing the rectangle with the x and y of release instead of width and height.
Replace
myRectangle = new Rectangle2D.Double(Start_X, Start_Y, myX2, myY2);
with
int x;
int y;
if (Start_X > myX2) {
x = myX2;
} else {
x = Start_X;
}
if (Start_Y > myY2) {
y = myY2;
} else {
y = Start_Y;
}
myRectangle = new Rectangle2D.Double(x, y, Math.abs(myX2 - Start_X), Math.abs(myY2 - Start_Y));
I'm trying to complete a project for school. It is partially completed when I get it. I cannot test anything I've written (except the layout, by commenting-out the error). I have an error for "Rect cannot be resolved to a type". Thinking that I did something wrong, I found this complete code posted online, and thought I'd see what differences there are. I get the same errors here...lots of them. What gives? Note* I'm not trying to pass this program in, just trying to see how it works, since I want mine to do the same thing.
/**
* DrawRects.java
*
* Allows the user to enter a number of rectangles using mouse input.
* Keeps previous rectangles around.
* Inspired by a C++ class demo by THC
*
* #author Scot Drysdale on 4/19/00. Modified to a JApplet 1/16/2012
* Modified to add a "clear" button and use an ArrayList on 1/18/2012
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
public class DrawRects extends JApplet implements MouseListener,
MouseMotionListener {
private static final long serialVersionUID = 1L;
private Point pressedPoint = null; // place where mouse pressed down
private Rect currentRect = null; // rectangle being dragged.
private ArrayList<Rect> boxes = new ArrayList<Rect>(); // a list of rectangles
private static final Color[] colors = { Color.red, Color.cyan, Color.magenta,
Color.yellow };
private int colorIndex = 0; // index into colors of current color
private JButton clearButton; // Button to clear the screen
private static final int APPLET_WIDTH = 520; // Width of the applet
private static final int APPLET_HEIGHT = 550; // Height of the applet
private static final int CANVAS_WIDTH = 500; // Width of the canvas
private static final int CANVAS_HEIGHT = 500; // Height of the applet
/**
* Initializes the applet
*/
public void init() {
addMouseListener(this);
addMouseMotionListener(this);
setSize(APPLET_WIDTH, APPLET_HEIGHT);
Container cp = getContentPane(); // Content pane holds components
cp.setLayout(new FlowLayout()); // Fill left to right, top to bottom
Canvas canvas = new Canvas();
cp.add(canvas); // The canvas is the only component
// Make a button to clear the canvas, set the button's background
// to cyan, and add it to the content pane.
clearButton = new JButton("Clear");
clearButton.setBackground(Color.cyan);
clearButton.addActionListener(canvas);
cp.add(clearButton);
setVisible(true); // Makes the applet (and its components) visible
}
// Captures the position at which the mouse is initially pressed.
// It creates a new currentRect object, because the previous one
// will have been added to the ListOfRects.
public void mousePressed(MouseEvent event) {
pressedPoint = event.getPoint();
currentRect = new Rect(pressedPoint.x, pressedPoint.y, 0, 0, Color.black);
}
/**
* Gets the current position of the mouse as it is dragged and draws a
* rectangle with this point and pressedPoint as corners. This creates a
* rubberbanding rectangle effect.
*
* #param event the event that caused this callback
*/
public void mouseDragged(MouseEvent event) {
if (currentRect != null) { // make sure that currentRect exists
Point pt = event.getPoint();
currentRect.setX(Math.min(pt.x, pressedPoint.x));
currentRect.setY(Math.min(pt.y, pressedPoint.y));
currentRect.setWidth(Math.abs(pt.x - pressedPoint.x));
currentRect.setHeight(Math.abs(pt.y - pressedPoint.y));
repaint();
}
}
/**
* Done dragging mouse, so add current Rect to ListOfRects.
*
* #param event the event that caused this callback
*/
public void mouseReleased(MouseEvent event) {
if (currentRect != null) { // make sure that currentRect exists
currentRect.setColor(colors[colorIndex]);
colorIndex = (colorIndex + 1) % colors.length;
boxes.add(currentRect);
currentRect = null; // currentRect now in the list, so can't reuse it
}
repaint();
}
// Provide empty definitions for unused event methods.
public void mouseClicked(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
public void mouseMoved(MouseEvent event) {}
/**
* The canvas to draw upon
*/
private class Canvas extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
/**
* Constructor to choose preferred size
*/
public Canvas() {
// Canvas is a subclass of JPanel. The way we set the size of
// a JPanel is by the setPreferredSize method. It takes a reference to
// a Dimension object, which just packages together a width and height.
setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
}
/**
* Draw the rectangles
*
* #param page the graphics object to draw on
*/
public void paintComponent(Graphics page) {
super.paintComponent(page);
page.setColor(Color.black);
page.drawRect(0, 0, CANVAS_WIDTH - 1, CANVAS_HEIGHT - 1); // Draw border
for (Rect rectangle : boxes) // Draw the saved rectangles
rectangle.fill(page);
if (currentRect != null) // Draw the rectangle being dragged out (if exists)
currentRect.draw(page);
}
/**
* Handle the button - provide an actionListener
* #param event the event that caused this callback
*/
public void actionPerformed(ActionEvent event) {
boxes.clear();
repaint();
}
}
}
There's nothing in the SDK named Rect.
There is, of course, java.awt.Rectangle, which may help you on your quest.
However, it looks like Rect was just some other class in the project you grabbed that you forgot to grab the source for (or the author didn't make it available).
It wouldn't require a special import or anything if it was in the same package as DrawRects (the default package, by the looks of it) or if it was, say, an inner class of DrawRects (which it's not).
I have a table (JTable) of values which is updated in real time about every 10 seconds (last 2 columns out of 4 updated, for each row). I want this table to continuous scroll up so I used the example from:
http://wiki.byte-welt.net/wiki/MarqueePanelV
The scrolling wraps around, first line is shown after last line and works fine except one thing:
When I do the update of the DefaultTableModel (I'm using setValueAt() function), the values are printed at their original position (like the table is not scrolled). Only the portion with the 2 columns is refreshed, created some fracture in the view. The view is corrected at the next scroll (in 100 milliseconds) but is still visible on the screen. More, since I'm stopping the scroll when mouse is over the table, the update will create a visible fracture in the table view.
Any idea on how can I fix this problem?
Here is a code example showing the problem:
package scrollingtable;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.table.DefaultTableModel;
class MarqueePanelV extends JPanel
implements ActionListener, AncestorListener, WindowListener {
private boolean paintChildren;
private boolean scrollingPaused;
private int scrollOffset;
private int wrapOffset;
private int preferredHeight = -1;
private int scrollAmount;
private int scrollFrequency;
private boolean wrap = false;
private int wrapAmount = 0;
private boolean scrollWhenFocused = true;
private Timer timer = new Timer(100, this);
/**
* Convenience constructor that sets both the scroll frequency and
* scroll amount to a value of 5.
*/
public MarqueePanelV() {
this(20, 1);
}
/**
*
* #param scrollFrequency
* #param scrollAmount
*/
#SuppressWarnings("LeakingThisInConstructor")
public MarqueePanelV(int scrollFrequency, int scrollAmount) {
setScrollFrequency(scrollFrequency);
setScrollAmount(scrollAmount);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
addAncestorListener(this);
}
/*
* Translate the location of the children before they are painted so it
* appears they are scrolling bottom to top
*/
#Override
public void paintChildren(Graphics g) {
// Need this so we don't see a flicker of the text before scrolling
if (!paintChildren) {
return;
}
int x = super.getPreferredSize().height;
// Normal painting as the components scroll bottom to top
Graphics2D g2d = (Graphics2D) g;
g2d.translate(0, -scrollOffset);
super.paintChildren(g);
g2d.translate(0, scrollOffset);
// Repaint the start of the components on the bottom edge of the panel once
// all the components are completely visible on the panel.
// (Its like the components are in two places at the same time)
if (isWrap()) {
//wrapOffset = scrollOffset - super.getPreferredSize().height - wrapAmount;
wrapOffset = scrollOffset - x - wrapAmount;
g2d.translate(0, -wrapOffset);
super.paintChildren(g);
g2d.translate(0, wrapOffset);
}
}
/*
* The default preferred size will be half the size of the components added to
* the panel. This will allow room for components to be scrolled on and off
* the panel.
*
* The default height can be overriden by using the setPreferredHeight() method.
*/
#Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.height = (preferredHeight == -1) ? d.height / 2 : preferredHeight;
return d;
}
#Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
public int getPreferredHeight() {
return preferredHeight;
}
/**
* Specify the preferred height on the panel. A value of -1 will cause the
* default preferred with size calculation to be used.
*
* #param preferredHeight preferred height of the panel in pixels
*/
public void setPreferredHeight(int preferredHeight) {
this.preferredHeight = preferredHeight;
revalidate();
}
/**
* Get the scroll amount.
*
* #return the scroll amount in pixels
*/
public int getScrollAmount() {
return scrollAmount;
}
/**
* Specify the scroll amount. The number of pixels to scroll every time
* scrolling is done.
*
* #param scrollAmount scroll amount in pixels
*/
public void setScrollAmount(int scrollAmount) {
this.scrollAmount = scrollAmount;
}
/**
* Get the scroll frequency.
*
* #return the scroll frequency
*/
public int getScrollFrequency() {
return scrollFrequency;
}
/**
* Specify the scroll frequency. That is the number of times scrolling
* should be performed every second.
*
* #param scrollFrequency scroll frequency
*/
public void setScrollFrequency(int scrollFrequency) {
this.scrollFrequency = scrollFrequency;
int delay = 1000 / scrollFrequency;
timer.setInitialDelay(delay);
timer.setDelay(delay);
}
/**
* Get the scroll only when visible property.
*
* #return the scroll only when visible value
*/
public boolean isScrollWhenFocused() {
return scrollWhenFocused;
}
/**
* Specify the scrolling property for unfocused windows.
*
* #param scrollWhenVisible when true scrolling pauses when the window
* loses focus. Scrolling will continue when
* the window regains focus. When false
* scrolling is continuous unless the window
* is iconified.
*/
public void setScrollWhenFocused(boolean scrollWhenFocused) {
this.scrollWhenFocused = scrollWhenFocused;
}
/**
* Get the wrap property.
*
* #return the wrap value
*/
public boolean isWrap() {
return wrap;
}
/**
* Specify the wrapping property. Normal scrolling is such that all the text
* will scroll from bottom to top. When the last part of the text scrolls off
* the bottom edge scrolling will start again from the bottom edge. Therefore
* there is a time when the component is blank as nothing is displayed.
* Wrapping implies that as the end of the text scrolls off the top edge
* the beginning of the text will scroll in from the bottom edge. So the end
* and the start of the text is displayed at the same time.
*
* #param wrap when true the start of the text will scroll in from the bottom
* edge while the end of the text is still scrolling off the top
* edge. Otherwise the panel must be clear of text before it
* will begin again from the bottom edge.
*/
public void setWrap(boolean wrap) {
this.wrap = wrap;
}
/**
* Get the wrap amount.
*
* #return the wrap amount value
*/
public int getWrapAmount() {
return wrapAmount;
}
/**
* Specify the wrapping amount. This specifies the space between the end of the
* text on the top edge and the start of the text from the bottom edge when
* wrapping is turned on.
*
* #param wrapAmount the amount in pixels
*/
public void setWrapAmount(int wrapAmount) {
this.wrapAmount = wrapAmount;
}
/**
* Start scrolling the components on the panel. Components will start
* scrolling from the bottom edge towards the top edge.
*/
public void startScrolling() {
paintChildren = true;
scrollOffset = -getSize().height;
timer.start();
}
/**
* Stop scrolling the components on the panel. The conponents will be
* cleared from the view of the panel
*/
public void stopScrolling() {
timer.stop();
paintChildren = false;
repaint();
}
/**
* The components will stop scrolling but will remain visible
*/
public void pauseScrolling() {
if (timer.isRunning()) {
timer.stop();
scrollingPaused = true;
}
}
/**
* The components will resume scrolling from where scrolling was stopped.
*/
public void resumeScrolling() {
if (scrollingPaused) {
timer.restart();
scrollingPaused = false;
}
}
/**
* Adjust the offset of the components on the panel so it appears that
* they are scrolling from bottom to top.
*/
#Override
public void actionPerformed(ActionEvent e) {
scrollOffset += scrollAmount;
int height = super.getPreferredSize().height;
if (scrollOffset > height) {
scrollOffset = isWrap() ? wrapOffset + scrollAmount : -getSize().height;
}
//System.out.println("scroll offset: " + scrollOffset);
repaint();
}
/**
* Get notified when the panel is added to a Window so we can use a
* WindowListener to automatically start the scrolling of the components.
*/
#Override
public void ancestorAdded(AncestorEvent event) {
SwingUtilities.windowForComponent(this).addWindowListener(this);
}
#Override
public void ancestorRemoved(AncestorEvent event) {
}
#Override
public void ancestorMoved(AncestorEvent event) {
}
// Implement WindowListener
#Override
public void windowOpened(WindowEvent e) {
startScrolling();
}
#Override
public void windowClosing(WindowEvent e) {
stopScrolling();
}
#Override
public void windowClosed(WindowEvent e) {
stopScrolling();
}
#Override
public void windowIconified(WindowEvent e) {
pauseScrolling(); }
#Override
public void windowDeiconified(WindowEvent e) {
resumeScrolling(); }
#Override
public void windowActivated(WindowEvent e) {
if (isScrollWhenFocused()) {
resumeScrolling();
}
}
#Override
public void windowDeactivated(WindowEvent e) {
if (isScrollWhenFocused()) {
pauseScrolling();
}
}
}
public class Main extends JDialog implements ActionListener {
private JTable table;
private DefaultTableModel model;
MarqueePanelV mpv = new MarqueePanelV();
private Timer timer2;
public static void main(String[] args) {
// TODO code application logic here
new Main();
}
Main() {
setSize(600, 400);
this.setLocation(300, 300);
table = new JTable();
model = new DefaultTableModel(20, 2);
table.setModel(model);
table.getColumnModel().getColumn(0).setPreferredWidth(280);
table.getColumnModel().getColumn(1).setPreferredWidth(280);
for(int i = 0; i < 20; i++) {
model.setValueAt(i, i, 0);
model.setValueAt(100 + i, i, 1);
}
mpv.add(table);
add(mpv);
mpv.setWrap(true);
mpv.setWrapAmount(0);
mpv.startScrolling();
table.addMouseListener(new MouseListener() {
// Implement MouseListener
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {
mpv.pauseScrolling();
}
#Override
public void mouseExited(MouseEvent e) {
mpv.resumeScrolling();
}
});
setVisible(true);
timer2 = new Timer(2000, this);
timer2.setInitialDelay(1000);
timer2.setDelay(2000);
timer2.start();
}
public void actionPerformed(ActionEvent e) {
for(int i = 0; i < 20; i++) {
model.setValueAt(100 + i, i, 1);
}
}
}
Problem was solved by calling mpv.repaint(); in the timer2 action:
package scrollingtable;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.table.DefaultTableModel;
class MarqueePanelV extends JPanel
implements ActionListener, AncestorListener, WindowListener {
private boolean paintChildren;
private boolean scrollingPaused;
private int scrollOffset;
private int wrapOffset;
private int preferredHeight = -1;
private int scrollAmount;
private int scrollFrequency;
private boolean wrap = false;
private int wrapAmount = 0;
private boolean scrollWhenFocused = true;
private Timer timer = new Timer(100, this);
/**
* Convenience constructor that sets both the scroll frequency and
* scroll amount to a value of 5.
*/
public MarqueePanelV() {
this(20, 1);
}
/**
*
* #param scrollFrequency
* #param scrollAmount
*/
#SuppressWarnings("LeakingThisInConstructor")
public MarqueePanelV(int scrollFrequency, int scrollAmount) {
setScrollFrequency(scrollFrequency);
setScrollAmount(scrollAmount);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
addAncestorListener(this);
}
/*
* Translate the location of the children before they are painted so it
* appears they are scrolling bottom to top
*/
#Override
public void paintChildren(Graphics g) {
// Need this so we don't see a flicker of the text before scrolling
if (!paintChildren) {
return;
}
int x = super.getPreferredSize().height;
// Normal painting as the components scroll bottom to top
Graphics2D g2d = (Graphics2D) g;
g2d.translate(0, -scrollOffset);
super.paintChildren(g);
g2d.translate(0, scrollOffset);
// Repaint the start of the components on the bottom edge of the panel once
// all the components are completely visible on the panel.
// (Its like the components are in two places at the same time)
if (isWrap()) {
//wrapOffset = scrollOffset - super.getPreferredSize().height - wrapAmount;
wrapOffset = scrollOffset - x - wrapAmount;
g2d.translate(0, -wrapOffset);
super.paintChildren(g);
g2d.translate(0, wrapOffset);
}
}
/*
* The default preferred size will be half the size of the components added to
* the panel. This will allow room for components to be scrolled on and off
* the panel.
*
* The default height can be overriden by using the setPreferredHeight() method.
*/
#Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.height = (preferredHeight == -1) ? d.height / 2 : preferredHeight;
return d;
}
#Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
public int getPreferredHeight() {
return preferredHeight;
}
/**
* Specify the preferred height on the panel. A value of -1 will cause the
* default preferred with size calculation to be used.
*
* #param preferredHeight preferred height of the panel in pixels
*/
public void setPreferredHeight(int preferredHeight) {
this.preferredHeight = preferredHeight;
revalidate();
}
/**
* Get the scroll amount.
*
* #return the scroll amount in pixels
*/
public int getScrollAmount() {
return scrollAmount;
}
/**
* Specify the scroll amount. The number of pixels to scroll every time
* scrolling is done.
*
* #param scrollAmount scroll amount in pixels
*/
public void setScrollAmount(int scrollAmount) {
this.scrollAmount = scrollAmount;
}
/**
* Get the scroll frequency.
*
* #return the scroll frequency
*/
public int getScrollFrequency() {
return scrollFrequency;
}
/**
* Specify the scroll frequency. That is the number of times scrolling
* should be performed every second.
*
* #param scrollFrequency scroll frequency
*/
public void setScrollFrequency(int scrollFrequency) {
this.scrollFrequency = scrollFrequency;
int delay = 1000 / scrollFrequency;
timer.setInitialDelay(delay);
timer.setDelay(delay);
}
/**
* Get the scroll only when visible property.
*
* #return the scroll only when visible value
*/
public boolean isScrollWhenFocused() {
return scrollWhenFocused;
}
/**
* Specify the scrolling property for unfocused windows.
*
* #param scrollWhenVisible when true scrolling pauses when the window
* loses focus. Scrolling will continue when
* the window regains focus. When false
* scrolling is continuous unless the window
* is iconified.
*/
public void setScrollWhenFocused(boolean scrollWhenFocused) {
this.scrollWhenFocused = scrollWhenFocused;
}
/**
* Get the wrap property.
*
* #return the wrap value
*/
public boolean isWrap() {
return wrap;
}
/**
* Specify the wrapping property. Normal scrolling is such that all the text
* will scroll from bottom to top. When the last part of the text scrolls off
* the bottom edge scrolling will start again from the bottom edge. Therefore
* there is a time when the component is blank as nothing is displayed.
* Wrapping implies that as the end of the text scrolls off the top edge
* the beginning of the text will scroll in from the bottom edge. So the end
* and the start of the text is displayed at the same time.
*
* #param wrap when true the start of the text will scroll in from the bottom
* edge while the end of the text is still scrolling off the top
* edge. Otherwise the panel must be clear of text before it
* will begin again from the bottom edge.
*/
public void setWrap(boolean wrap) {
this.wrap = wrap;
}
/**
* Get the wrap amount.
*
* #return the wrap amount value
*/
public int getWrapAmount() {
return wrapAmount;
}
/**
* Specify the wrapping amount. This specifies the space between the end of the
* text on the top edge and the start of the text from the bottom edge when
* wrapping is turned on.
*
* #param wrapAmount the amount in pixels
*/
public void setWrapAmount(int wrapAmount) {
this.wrapAmount = wrapAmount;
}
/**
* Start scrolling the components on the panel. Components will start
* scrolling from the bottom edge towards the top edge.
*/
public void startScrolling() {
paintChildren = true;
scrollOffset = -getSize().height;
timer.start();
}
/**
* Stop scrolling the components on the panel. The conponents will be
* cleared from the view of the panel
*/
public void stopScrolling() {
timer.stop();
paintChildren = false;
repaint();
}
/**
* The components will stop scrolling but will remain visible
*/
public void pauseScrolling() {
if (timer.isRunning()) {
timer.stop();
scrollingPaused = true;
}
}
/**
* The components will resume scrolling from where scrolling was stopped.
*/
public void resumeScrolling() {
if (scrollingPaused) {
timer.restart();
scrollingPaused = false;
}
}
// Implement ActionListener
/**
* Adjust the offset of the components on the panel so it appears that
* they are scrolling from bottom to top.
*/
#Override
public void actionPerformed(ActionEvent e) {
scrollOffset += scrollAmount;
int height = super.getPreferredSize().height;
if (scrollOffset > height) {
scrollOffset = isWrap() ? wrapOffset + scrollAmount : -getSize().height;
}
repaint();
}
// Implement AncestorListener
/**
* Get notified when the panel is added to a Window so we can use a
* WindowListener to automatically start the scrolling of the components.
*/
#Override
public void ancestorAdded(AncestorEvent event) {
SwingUtilities.windowForComponent(this).addWindowListener(this);
}
#Override
public void ancestorRemoved(AncestorEvent event) {
}
#Override
public void ancestorMoved(AncestorEvent event) {
}
// Implement WindowListener
#Override
public void windowOpened(WindowEvent e) {
startScrolling();
}
#Override
public void windowClosing(WindowEvent e) {
stopScrolling();
}
#Override
public void windowClosed(WindowEvent e) {
stopScrolling();
}
#Override
public void windowIconified(WindowEvent e) {
pauseScrolling(); }
#Override
public void windowDeiconified(WindowEvent e) {
resumeScrolling(); }
#Override
public void windowActivated(WindowEvent e) {
if (isScrollWhenFocused()) {
resumeScrolling();
}
}
#Override
public void windowDeactivated(WindowEvent e) {
if (isScrollWhenFocused()) {
pauseScrolling();
}
}
}
public class Main extends JDialog implements ActionListener {
private JTable table;
private DefaultTableModel model;
MarqueePanelV mpv = new MarqueePanelV();
private Timer timer2;
public static void main(String[] args) {
// TODO code application logic here
new Main();
}
Main() {
setSize(600, 400);
this.setLocation(300, 300);
table = new JTable();
model = new DefaultTableModel(20, 2);
table.setModel(model);
table.getColumnModel().getColumn(0).setPreferredWidth(280);
table.getColumnModel().getColumn(1).setPreferredWidth(280);
for(int i = 0; i < 20; i++) {
model.setValueAt(i, i, 0);
model.setValueAt(100 + i, i, 1);
}
mpv.add(table);
add(mpv);
mpv.setWrap(true);
mpv.setWrapAmount(0);
mpv.startScrolling();
table.addMouseListener(new MouseListener() {
// Implement MouseListener
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {
mpv.pauseScrolling();
}
#Override
public void mouseExited(MouseEvent e) {
mpv.resumeScrolling();
}
});
setVisible(true);
timer2 = new Timer(2000, this);
timer2.setInitialDelay(1000);
timer2.setDelay(2000);
timer2.start();
}
int k = 0;
public void actionPerformed(ActionEvent e) {
for(int i = 0; i < 20; i++) {
model.setValueAt(100 + i + k, i, 1);
}
k++;
mpv.repaint();
}
}
I have a main frame and a attached collapsible panel that i got from http://sourceforge.net/apps/wordpress/miasct/2009/03/29/external-collapsible-panel/.
The problem is collapsible panel creates undecorated frame that extends JFrame (actually JXFrame from SwingX) and behaves like one.
How do i get rid of this:
Dont show it in alt+tab thingy
When i use "minimize all windows" in WindowsOS and then maximize main frame, attached frame stays iconified.
Here's a code for it:
import com.sun.jna.platform.WindowUtils;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JFrame;
import org.jdesktop.swingx.JXFrame;
import ui.MainFrame;
/**
* CollapsibleFrame
*
* #author Devon Bryant
* #since Mar 26, 2009
*/
#SuppressWarnings("serial")
public class CollapsibleFrame extends JXFrame implements ICollapsibleFrame
{
// The parent frame to tie this frame to
private JFrame parentFrame = null;
// Orientation (where the collapsible frame is located relative to the parent frame)
private Orientation orientation = null;
/**
* Constructor
* #param inName the frame name
* #param inParentFrame the parent frame to tie this frame to
* #param the orientation (where in respect to the parent frame to attach to)
*/
public CollapsibleFrame(String inName, JFrame inParentFrame, Orientation inOrientation)
{
super(inName);
parentFrame = inParentFrame;
orientation = inOrientation;
setUndecorated(true);
}
/* (non-Javadoc)
* #see com.mia.sct.view.panel.ICollapsibleFrame#relocate()
*/
#Override
public void relocate()
{
offset(0, 0);
}
/* (non-Javadoc)
* #see com.mia.sct.view.panel.ICollapsibleFrame#offset(int, int)
*/
#Override
public void offset(int inX, int inY)
{
if ((parentFrame != null && parentFrame.isVisible()))
{
Point p = null;
int x = 0;
int y = 0;
// Calculate the new x,y coordinates for this frame based on the parents location
switch (orientation)
{
case TOP:
p = parentFrame.getLocationOnScreen();
x = p.x;
y = p.y - getHeight();
break;
case BOTTOM:
p = parentFrame.getLocationOnScreen();
x = p.x;
y = p.y + parentFrame.getHeight();
break;
case LEFT:
p = parentFrame.getLocationOnScreen();
x = p.x - getWidth();
y = parentFrame.getContentPane().getLocationOnScreen().y;
break;
case RIGHT:
p = parentFrame.getLocationOnScreen();
x = p.x + parentFrame.getWidth();
y = parentFrame.getContentPane().getLocationOnScreen().y;
break;
}
x += inX;
y += inY;
// set the location of this frame
setLocation(x, y);
}
}
/* (non-Javadoc)
* #see com.mia.sct.view.panel.ICollapsibleFrame#setMask(java.awt.Shape)
*/
public void setMask(Shape inShape)
{
WindowUtils.setWindowMask(this, inShape);
}
/* (non-Javadoc)
* #see com.mia.sct.view.panel.ICollapsibleFrame#setAlpha(float)
*/
public void setAlpha(float inAlpha)
{
if (WindowUtils.isWindowAlphaSupported())
{
WindowUtils.setWindowAlpha(this, inAlpha);
}
}
}
Thanks in advance.
not good idea hold two JFrames (or its SwingX derivates) in same time, you have to change that for Un-Decorated JDialog or JWindow (its SwingX derivates), that solving three issues and you can correctly to set
setParent
setModal, ModalityTypes
no iconified in WinOS