JFrame Resize Issues (Redux)

Discussion in 'Java' started by kc, Jul 5, 2005.

  1. kc

    kc Guest

    Greetings,

    I decided to make a new topic out of this to start fresh. First, let's
    get to the problem. I am developing Java on a Windows platform (that's
    not the problem) and I am using a JFrame with a component inside that
    must be sized according a certain aspect ratio. The problem I am
    encountering is when I decorate the frames with a LookAndFeel
    (javax.JFrame.setDefaultLookAndFeelDecorated(true)) the
    componentResize() behavior changes drastically. On Windows, the user
    can resize to their hearts' content and when they let go of the mouse
    button, the resize event is sent and the window resizes to aspect
    ratio. However, when the LookAndFeel is set, Java's Window Manager
    takes over and the componentResize event is sent while the user is
    resizing, say every pixel or two.

    Now, that wouldn't be a problem (in fact, it would be nice if the
    window maintained aspect ratio while the user dragged it) if it wasn't
    so ugly and hard to control. For that I'll let you run the source code
    that I prepared below. (it is 247 lines, and compiles in Borland
    JBuilder X - and again, that isn't the problem). Now the reason this
    is vitally important is because the application is fully intended to be
    cross platform, so I can't always depend on things working the Windows
    Window Manager way, so instead I'm ditching that and trying to just do
    things the Java WM way.

    A couple of notes before you run:

    1. Two windows will pop up when you run the app. One will be decorated,
    the other not. If you close one, it will close both and the app will
    end.
    2. A big red X goes across where "video" will be showing. I use no
    "special" components for the video, my application doesn't even really
    play video, it just controls the hardware that overlays it, so that
    isn't an issue.
    3. I'm using the swing.plaf.metal look and feel. If your debug area
    says, "Er... crap." then you failed to load that component. You may
    choose to use your own look and feel provided that it has its own
    window frame decoration (for instance, Motif does not I don't think).

    Anyway, thank you for your help, it is greatly appreciated. Without
    further adeiux (sp?), here's the code:

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

    public class videoGui
    extends JFrame
    implements ActionListener {
    public static videoGui videoControl;
    public static videoGui videoControl2;
    public int fvnumber; /* Ufg ProcId */
    public int mixernumber; /* Mixer ProcId */

    public String titleLabel = "";
    public String window_char;

    public int OffSetX = 0;
    public int OffSetY = 0;
    public Rectangle normalbounds = new Rectangle();
    public String popups = "centerscreen";

    // Window size values
    public int source_width;
    public int source_height;
    private Rectangle positRectangle;
    private int diffHeight;
    private int diffWidth;
    private int oldHeight;
    private int oldWidth;
    public float ratio;
    private boolean first_time = true;
    private boolean mouse_down = false;

    // Create objects inside the video gui
    public GUICanvas videoCanvas;
    private JPanel forButtons;
    private JMenuBar topPanel;

    public videoGui(int ufg, int mix) {
    fvnumber = ufg;
    mixernumber = mix;
    initGUI();
    }

    static public void main(String[] args) {
    videoControl = new videoGui(0, 0);
    videoControl.setTitle("Good");
    videoControl.setVisible(true);
    try {

    UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
    javax.swing.JFrame.setDefaultLookAndFeelDecorated(true);
    }
    catch (Exception E) {
    System.out.println("Er... crap.");
    }
    videoControl2 = new videoGui(0, 0);
    videoControl2.setTitle("Bad");
    videoControl2.setVisible(true);
    videoControl2.setLocation(30, 30);
    }

    private void initGUI() {
    GetInfo();
    createMenuBar();
    doTheLayout();

    this.setFocusable(true);

    this.addComponentListener(new ComponentAdapter() {
    public void componentHidden(ComponentEvent evt) {

    }

    public void componentMoved(ComponentEvent evt) {
    setPortPosition();
    }

    public void componentResized(ComponentEvent evt) {
    resizeVideo();
    setPortPosition();
    }

    public void componentShown(ComponentEvent evt) {
    resizeVideo();
    setPortPosition();
    }
    });

    this.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent evt) {
    closeout();
    }

    public void windowClosed(WindowEvent evt) {
    closeout();
    }

    public void windowDeiconified(WindowEvent evt) {
    setPortPosition();
    }

    public void windowIconified(WindowEvent evt) {
    }

    public void windowActivated(WindowEvent evt) {
    setPortPosition();
    }

    public void windowDeactivated(WindowEvent evt) {
    }

    public void windowOpened(WindowEvent evt) {
    setPortPosition();
    }
    });
    }

    public void GetInfo() {
    source_width = 640;
    source_height = 480;
    ratio = ( ( float ) source_width ) / ( ( float ) source_height
    );
    }


    public JMenuBar createMenuBar() {
    topPanel = new JMenuBar();

    JLabel label = new JLabel("Moo");
    topPanel.add(label);

    forButtons = new JPanel();
    forButtons.setLayout(new GridLayout(1, 7, 0, 0));
    forButtons.add(topPanel);
    return topPanel;
    }

    private void doTheLayout() {
    videoCanvas = new GUICanvas(this);
    videoCanvas.setSize(source_width, source_height);
    videoCanvas.setOpaque(true);

    this.getContentPane().setLayout(new BorderLayout());

    this.getContentPane().add(videoCanvas, "Center");
    this.getContentPane().add(forButtons, "South");
    this.setSize(source_width, source_height);

    String popupBehavior = "centerscreen";
    popups = popupBehavior;
    }

    public void setPortPosition() {
    Point newLoc;
    positRectangle = getBounds();
    if (this.isVisible()) {
    newLoc = videoCanvas.getLocationOnScreen();
    }
    else {
    newLoc = new Point(0, 0);
    }
    int AbsoluteX = newLoc.x - OffSetX;
    int AbsoluteY = newLoc.y - OffSetY;
    }

    private void resizeVideo() {
    int newWidth = this.getWidth();
    int newHeight = this.getHeight();
    int vidWidth = videoCanvas.getWidth();
    int vidHeight = videoCanvas.getHeight();
    int inHeight;
    int inWidth;

    if (first_time) {
    oldHeight = newHeight;
    oldWidth = newWidth;
    diffHeight = oldHeight - vidHeight;
    diffWidth = oldWidth - vidWidth;
    oldHeight = source_height + diffHeight;
    oldWidth = source_width + diffWidth;

    newHeight = oldHeight;
    newWidth = oldWidth;

    first_time = false;
    }
    /* Check to see if we want to maintain aspect ratio.
    In this case it is permenantly YES */
    if ("a".equals("a")) {
    if (newHeight != oldHeight || newWidth != oldWidth) {
    // Keep aspect ratio
    if (java.lang.Math.abs(oldHeight - newHeight) >=
    java.lang.Math.abs(oldWidth - newWidth)) {
    oldHeight = newHeight;
    inHeight = oldHeight - diffHeight;
    inWidth = (int) (ratio * ( (float) inHeight));
    oldWidth = inWidth + diffWidth;
    }
    else {
    oldWidth = newWidth;
    inWidth = oldWidth - diffWidth;
    inHeight = (int) ( ( (float) inWidth) / ratio);
    oldHeight = inHeight + diffHeight;
    }
    }
    this.setSize(oldWidth, oldHeight);
    }
    else {
    oldHeight = newHeight;
    oldWidth = newWidth;
    }
    /*fvmain.SetSize( fvnumber,
    this.videoCanvas.getWidth(),this.videoCanvas.getHeight() );*/
    }

    private void closeout() {
    System.exit(0);
    }

    public void actionPerformed(ActionEvent evt) {
    }

    // First panel which opens Video Panel
    public class GUICanvas
    extends JComponent {

    private String msg = "";
    public int mouseX = 0;
    public int mouseY = 0;
    public int prevX = 0;
    public int prevY = 0;
    public boolean rubberBand = true;
    public Color canvasColor = new java.awt.Color(0, 0, 0);
    private videoGui videowindow;

    public GUICanvas(videoGui v) {
    videowindow = v;
    repaint();
    }

    public void paintComponent(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    g2d.setColor( canvasColor );
    g2d.fillRect(0, 0, this.getWidth(), this.getHeight());
    g2d.setColor(Color.red);
    g2d.drawLine(0, 0, this.getWidth(), this.getHeight());
    g2d.drawLine(this.getWidth(), 0, 0, this.getHeight());
    }
    }
    }
     
    kc, Jul 5, 2005
    #1
    1. Advertising

  2. Hi KC!

    I just ran your GUI and noticed something that surprised me.

    I had always thought you meant to resize the inner vidoe component to
    'fill to the maximum of either height or width that is available,
    then PAD the other'[1] (e.i. Stretch to maximum height and pad width,
    or fill to width and pad height)

    It seems that might be[2] both easier to do, and less likely to
    interfere with the window sizing.

    Would 'pad with black[3]' work for your application?

    [1] The red 'X' certainly helped!
    [2] Untested hunch.
    [3] Choose your color, ..any color.

    --
    Andrew Thompson
    http://www.PhySci.org/codes/ Web & IT Help
    http://www.PhySci.org/ Open-source software suite
    http://www.1point1C.org/ Science & Technology
    http://www.LensEscapes.com/ Images that escape the mundane
     
    Andrew Thompson, Jul 6, 2005
    #2
    1. Advertising

  3. On Wed, 06 Jul 2005 06:40:04 GMT, Andrew Thompson wrote:

    > Hi KC!


    Or rather - 'kc' (..oops!)
     
    Andrew Thompson, Jul 6, 2005
    #3
  4. kc

    kc Guest

    Hello,

    Thanks for the reply. In a sort of roundabout way I kind of do what
    you're suggesting. That is, I resize to the aspect ratio based on one
    of either height or width. It is a little less predictable than I
    would like, but it has worked fine in the past. At any rate, I has
    halfway through a Dairy Queen Blizzard yesterday when an idea hit me
    and it seems to have (somewhat) fixed my problem, and in turn a new
    problem has surfaced. The new problem is not nearly as bad, however,
    and if it isn't fixable then that is okay.

    The fix is to detect a mousedown use a semaphore that basically says,
    "Don't you dare do that aspect ratio thing right now!" Instead, when
    the user resizes while the mouse button is down, the componentResize
    event sets yet another semaphore, in this case mouse_resize to true
    which basically says, "While the mouse button was down, the user
    resized". Now when the user releases the mouse button, it calls the
    resizeVideo() function if the mouse_resize flag is true.

    The problem is that while the user is resizing, some flickering, grey
    striping occurs. I am guessing that this is because the JFrame is not
    double buffered (the striping goes all the way up through the title bar
    and such). My GUICanvas is double buffered, so I thought it wouldn't
    affect this, but it does... So alas, I am unhappy. If you have any
    idea what may be causing this flickering effect and any way to fix it,
    please let me know.

    If you want to add in my fix to the test application I sent along,
    simply replace the initGUI() method with this one and add the
    appropriate variables at the top:
    private boolean mouse_down = false;
    private boolean mouse_resized = false;

    private void initGUI() {
    GetInfo();
    createMenuBar();
    doTheLayout();

    this.setFocusable(true);

    this.addMouseListener(new MouseListener() {
    public void mouseClicked(MouseEvent me) {

    }
    public void mouseEntered(MouseEvent me) {

    }
    public void mouseExited(MouseEvent me) {

    }
    public void mousePressed(MouseEvent me) {
    mouse_down = true;
    }
    public void mouseReleased(MouseEvent me) {
    if ( mouse_resized = true ) {
    resizeVideo();
    setPortPosition();
    mouse_resized=false;
    mouse_down=false;
    }
    }
    });
    this.addComponentListener(new ComponentAdapter() {
    public void componentHidden(ComponentEvent evt) {

    }

    public void componentMoved(ComponentEvent evt) {
    setPortPosition();
    }

    public void componentResized(ComponentEvent evt) {
    if ( mouse_down == false ) {
    resizeVideo();
    setPortPosition();
    } else {
    mouse_resized = true;
    }
    }

    public void componentShown(ComponentEvent evt) {
    resizeVideo();
    setPortPosition();
    }
    });

    this.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent evt) {
    closeout();
    }

    public void windowClosed(WindowEvent evt) {
    closeout();
    }

    public void windowDeiconified(WindowEvent evt) {
    setPortPosition();
    }

    public void windowIconified(WindowEvent evt) {
    }

    public void windowActivated(WindowEvent evt) {
    setPortPosition();
    }

    public void windowDeactivated(WindowEvent evt) {
    }

    public void windowOpened(WindowEvent evt) {
    setPortPosition();
    }
    });
    }

    Thanks for the help!
     
    kc, Jul 6, 2005
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    9
    Views:
    1,459
    Raymond DeCampo
    Jul 1, 2005
  2. jakester
    Replies:
    3
    Views:
    1,898
    jakester
    Apr 3, 2007
  3. Replies:
    2
    Views:
    1,296
    Adrienne
    Feb 13, 2005
  4. Replies:
    2
    Views:
    439
    markspace
    Aug 27, 2012
  5. K

    JFrame issues

    K, Dec 3, 2012, in forum: Java
    Replies:
    3
    Views:
    393
    Arne Vajhøj
    Dec 4, 2012
Loading...

Share This Page