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