Get height of JDialog title bar? - java

How can I get the height of JDialog title bar?
I've tried with getInsets().top, but it returns 0.

Give this a try:
Container c = this.getContentPane();
Point pt = c.getLocation();
pt = SwingUtilities.convertPoint(c, pt, this);
The pt variable now holds the location of the content pane, relative to the origin of the JDialog. Therefore, pt.x is the distance from the left edge and pt.y is the distance from the top.
Caveats:
This assumes no JMenuBar. If you have one, use the location of the JMenuBar instead.
This will include any borders added to the contentPane, or the layerdPane. You'll need to subtract those out.

I don't know if, if you're using OS's own window manager, this may not be possible. The reason is that, the title bar is drawn outside Java. If you really need this information you will probably need to use JNI.
However, if you are using internal frames, you can do the following
JInternalFrame mydialog = new JInternalFrame();
((BasicInternalFrameUI)mydialog.getUI()).getNorthPane().getHeight();
But a more important question is, why do you want to know? The idea of a windowing system is so that the programmer can abstract the content of his application from the window environment. This is so that window appearances can be customised dynamically by the user, look homogeneous across all apps, and not interfere with the application's normal running.
Such an interface between OS and app would require a whole message-passing API to inform when window decorations change etc.

kofucii, you are on the right path - use the dialog getInsets().top as you did in your example.
I guess you got 0 probably because the JDialog object was invisible. Otherwise the 'top' value should be ~36 ...
Here is an isolated case:
package dejan.various;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
/**
*
* #author dejan
*/
public class TestDialog extends JDialog implements ActionListener {
private javax.swing.JButton testButton;
public TestDialog() {
setPreferredSize(new Dimension(640,480));
getContentPane().setLayout(new BorderLayout());
testButton = new JButton("Click me");
testButton.addActionListener(this);
getContentPane().add(testButton, BorderLayout.SOUTH);
pack();
}
#Override
public void actionPerformed(ActionEvent e) {
Insets insets = this.getInsets();
System.out.println(insets.top);
System.out.println(insets.left);
}
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new TestDialog().setVisible(true);
}
});
}
} // TestDialog class
On the STDOUT I get:
36
9

To get insets you need to make sure your JDialog is visible. if you try to get it before showing on screen you got 0.

Related

Show multiple JPane images on a single JFrame

First off, I am new to JFrame and all the associated classes so I am still learning how to do this.
My current goal is to draw multiple images on a single JFrame. So far, I can get test2.png to draw, but not test1.png. Any suggestions or help understanding JFrame is appreciated. This is my main class:
package com.osj.oneshotjava;
import java.awt.Dimension;
import javax.swing.JFrame;
/**
*
* #author BCG04
*/
public class actorTest {
public static void main(String []args){
JFrame jFrame = new JFrame("OSJ actor test");
jFrame.setPreferredSize(new Dimension(640, 480)); // sets window size
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Actor2 Background = new Actor2(jFrame, "test1.png");
Actor2 testActor = new Actor2(jFrame, "test2.png");
jFrame.pack(); // automatically adjusts window size (also sets window size based on the maximum and minimum sizes)
jFrame.setVisible(true);
}
}
And this is Actor2:
package com.osj.oneshotjava;
import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
*
* #author BCG04
*/
public class Actor2 { //Purpose: make it easer to add multiple images to a single JFrame using only a single call to Actor2's constuctor rather than repeating the same section of code for each image.
private BufferedImage image = null;
private JLabel jLabel = null;
public Actor2(JFrame jFrame, String filename){
try
{ // try to load a image 'filename' into 'image'
image = ImageIO.read(new File(filename));
}
catch (Exception e)
{
e.printStackTrace(); // if loading fails, print the error
System.exit(1); // then exit with an error code 1 'unsuccessful exit'
}
ImageIcon imageIcon = new ImageIcon(image); // create a new ImageIcon that contains 'image'
JPanel jPanel = new JPanel();
jLabel = new JLabel();
jLabel.setIcon(imageIcon); // set JLabel 'jLabel' to contain 'imageIcon'
jPanel.add(jLabel);
jFrame.getContentPane().add(jPanel, BorderLayout.CENTER); // makes window visible?
}
public JLabel getJLabel(){
return jLabel;
}
}
Edit:
-removed Thread.sleep(1000); and setLocation(90, 90); since they were not relevant to the question or the problem and I originally had them in to test whether I could move images.
-removed jLabel.setBounds as it did not seem to do anything.
+added a comment clarifying Actor2's goal.
I'd like to clarify my end goal, I would like to create a simple 2d game that uses Java.
Here is a complete, self contained example that is close to what you're after. It is to demonstrate the use of a layout manager.
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
public class DuelingJLabels{
public static void startGui(){
JFrame frame = new JFrame();
JPanel scene = new JPanel();
Actor red = new Actor(Color.RED);
Actor blue = new Actor(Color.BLUE);
//scene.setLayout( null );
scene.add(red.image);
scene.add(blue.image);
//scene.setPreferredSize( new Dimension(512, 512) );
frame.add(scene, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
static class Actor{
int x, y;
JLabel image;
public Actor(Color c){
BufferedImage a = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics g = a.getGraphics();
g.setColor(c);
g.fillOval(0, 0, 64, 64);
image = new JLabel();
image.setIcon(new ImageIcon(a));
image.setLocation( x, y );
image.setSize( 64, 64);
image.addMouseListener( new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent evt){
x = x+64;
if(x>=448){
x = 0;
y += 64;
}
image.setLocation(x, y);
}
});
}
}
public static void main(String[] args){
EventQueue.invokeLater( DuelingJLabels::startGui );
}
}
Take note of the line scene.setLayout(null); if you run the example with that line commented out, then you will see two circles side by side. That is because we are letting swing handle the layout. scene is a JPanel with a FlowLayout by default.
Now when you click the circles, nothing happens* because we tell the new position but the layout manager resets the position.
*Actually they move sometimes, but if you trigger a re-validation then they get moved by the layout manager.
So now remove the comment on scene.setLayout(null); and notice the difference.
The frame is tiny, and we have to manually resize it to see our scene.
There is only one circle.
If you click on the circle, it moves.
That's because we have told swing to not use a layout manager for the JPanel scene. That means it will not reposition the components in the scene for us, and it will not adjust the sizes for us either.
The other line that is commented setPreferredSize makes scene tell the parent component a size it would like to be at. If you uncomment that line then the JFrame will not start out incredibly small. You should only use that with custom components, otherwise you can end up conflicting with the layout manager.
Another tool, which I have found usefull is the JLayeredPane because it gives you some depth. I also think the example is good.
Finally, another technique for putting custom graphics arbitrarily is to #Override paintComponent. That way you can draw whatever, where-ever on your component.

How to Move JLabes Around

import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Gui_Window extends JFrame {
private JLabel Main_L;
public Gui_Window() {
setLayout(new FlowLayout());
Main_L = new JLabel("Did you know it is possible to bind keys?");
add(Main_L);
}
public static void main (String args[]) {
Gui_Window gui = new Gui_Window();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setSize(300,300);
gui.setVisible(true);
gui.setTitle("Gamers AudioMute");
gui.setResizable(true);
}
}
I would like to know how to move my "Did you know" Label around. Could you also state how to align left, right, middle and how to move it around by its coordinates?
You can use methods included in Swing classes. Try
mainL.setHorizontalAlignment(SwingConstants.LEFT);
mainL.setVerticalAlignment(SwingConstants.BOTTOM);
The two methods setHorizontalAligment and setVeritcalAlignment both take integers that will set the start of either the horizontal or vertical component of the label to that pixel integer within the Swing window.
You should also read up on SwingConstants which allow you to plug in pre-defined integers by Swing that will align your texts to desirable locations within the panel. Here's a link
http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingConstants.html
They are also useful when manipulating different layouts such as BorderLayout and GridLayout.

How to make JSplitPane auto expand on mouse hover?

I want to make a Java program with Swing layout where there is a menu on the left that is expanded when a mouse hovers over the menu area, but auto contracts after your mouse leaves.
I am trying to imitate the effect of something like mobile Youtube for Android, or Weebly's editor. Fro those who don't know, both layouts have menus on the left that expand when your mouse hovers over them. Then after your mouse leaves the area, the menu contracts again and is out of view.
I was able to create the JSplitPane containing my menu successfully, but I have no idea how to make it automatically expand when the user's mouse hovers over the JSplitPane component, or how to make it contract after the mouse leaves the area.
In case anyone is wondering why: This type of menu is easy for the user to use but because it hides away when unneeded, allows me to have more space for the main part of the program.
Any help would be appreciated thanks!
Well make use of jSplitPan.setDividerLocation(location);: Sets the location of the divider. location - an int specifying a UI-specific value (typically a pixel count).
jSplitPane1.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent evt) {
// use evt.getSource() if needed
jSplitPan1.setDividerLocation(location);
}
});
You will probably need to compute the divider location a little bit intelligently. hints: by computing the relevant preferred-size hints. The part relevant should be discovered by you.
Take a look into official tutorial page to know: How to use MouseMotionListeners including other event listeners.
There are two basic problems...
You need to detect when the mouse hovers over the divider and
When it exists the "menu"
The second is relatively easy, you can use a MouseListener and monitor the mouseExit event, setting the position of the split pane divider as the mouse leaves.
This is complicated though, as if the user exists the "menu" by crossing over the divider, this may trigger the "menu" to made visible again...
The first problem is more complicated, as the JSplitPane contains three components, the left and right components, but also a divider component. JSplitPane doesn't actually allow access to the divider, which is rather annoying and because it uses it's own mouse listener, it blocks mouse events going to the split itself.
Instead, you need to gain access to it via the UI delegate.
Once you've set up the mouse listener, you need to ensure that the menu will only be shown when the menu is hidden, for this, I simply checked the size of the "menu" component
For example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;
public class TestSpltPane {
public static void main(String[] args) {
new TestSpltPane();
}
public TestSpltPane() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
final JPanel left = new JPanel();
left.setBackground(Color.RED);
left.setPreferredSize(new Dimension(100, 100));
JPanel right = new JPanel();
right.setBackground(Color.BLUE);
right.setPreferredSize(new Dimension(100, 100));
final JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, right);
sp.setDividerLocation(0);
BasicSplitPaneDivider divider = ((BasicSplitPaneUI) sp.getUI()).getDivider();
divider.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
if (left.getWidth() == 0) {
sp.setDividerLocation(100);
}
}
});
left.addMouseListener(new MouseAdapter() {
#Override
public void mouseExited(MouseEvent e) {
sp.setDividerLocation(0);
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(sp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

I want to make my frame close when the X(close button) is clicked

I have a small template that ive built for the purpose of implementing an applet through a simple java application via netbeans 7.1 (as in not using Javacard, Netbeans Platform etc ..just a simple java application with applet initialized when application runs)
I have managed to make it invoke the applet when i press the run button in netbeans and i ahve functionality inside the applet but, i cant seem to get it to close and i have a horrible feeling people are gonna tell me to have used jFrame and implement the EXIT_ON_CLOSE method.
This is NOT something I would like to know how to do , my mission is to implement it using Frames != jFrames.
I hope someone can help as its bugged me for a bit now and i have to get on with Java assignment that involves its use.
Enclosed is the code/classes for A: the appletframe and B:the applet
* 1.4 Write an applet to display a line of text.
* The text should then change its font size and style (bold, italic, underline)
* depending on where the mouse is clicked on the screen.
*/
package appletframe;
import java.awt.Graphics;
import java.awt.Frame;
import java.applet.Applet;
/**
* #author MuthaLoad aka Gruffy2012
*/
import java.awt.*;
public class AppletFrame extends Applet{
public static void main(String[] args) {
/*construct needs object instances*/
MrApplet mrApplet = new MrApplet(); // create instance/obj of MrApplet
Frame myFrame = new Frame("Applet"); // create frame "title optional"
//setDefaultCloseOperation(myFrame.EXIT_ON_CLOSE);(jFrame- not wanted)
/* add applet to the frame*/
//myFrame.addWindowListener();
myFrame.add(mrApplet, BorderLayout.CENTER);
myFrame.setBounds(10,10,500,500);
myFrame.setVisible(true); // step to make frame visible
/*initialize instance of mrApplet*/
mrApplet.init();
} // end main
} // end class
B: applet
package appletframe;
import java.awt.*; //for buttons
import java.awt.event.*; //for events
import java.applet.*; //main applet api`s
import java.awt.Graphics; //graphics
public class MrApplet extends Applet implements ActionListener
{
private static final long serialVersionUID = 1L;
Button btnClick;
String msg = "";
public void init()
{
// TODO start asynchronous download of heavy resources
setSize(500, 500);
Button btnClick = new Button("Press Me ");
btnClick.addActionListener(this);
add(btnClick);
}
public void actionPerformed(ActionEvent e)
{
//throw new UnsupportedOperationException("Not supported yet.");
msg = "Yay, the button works";
repaint();
}
public void paint (Graphics g)
{
g.setFont(new Font("Serif", Font.ITALIC, 30)); //new font obj, font , font style, font size
g.setColor(new Color(0,255,0)); //new color obj, r,g,b
g.drawString(msg, 40, 80);
}
// TODO overwrite start(), stop() and destroy() methods
}
Once again thanks for reading, and to clarify any confusions..
I am looking for a pointer as to the solution of closing my applet and frame window upon exit , without reimplementing it all using jFrame, though i know this would be easier in the first instance.
Thankyou and as always, indebted to all your advice.
gruffy321
add this line at the end of ApplicationFrame class.
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
You want to do it with Frame not with JFrame, then you have to add the WindowListener event to the frame and have to override windowClosing() method.
myFrame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we){
System.exit(0);
});

setBorder method for JLabel causing paint problem

I have a custom class that extends JLabel. For specific instances of that class, I want to add some spacing to the text on the left side. I need the spacing as I'm setting the background of this JLabel and I don't want the text to bump up right next to the edge of the colored background. I fished around quite a bit and implemented this (inside the paint function):
if (condition) {
bgColor = Color.red;
setBackground(bgColor);
setOpaque(true);
// This line merely adds some padding on the left
setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
}
else {
setOpaque(false);
}
This appears to work in that it adds the spacing I want, however it has an unfortunate side effect in that it appears to break the repainting of the whole rest of the application...it appears that only that particular component is repainting and not the rest of the application. I eventually tracked it down to the setBorder call specifically...setting ANY kind of border appears to cause the same broken behavior. We have two different versions of our application, one that runs in Java 1.5 and one that runs in Java 1.6, the Java 1.6 version appears to work correctly while the Java 1.5 version doesn't. It is not possible to upgrade the older version to Java 1.6...I need something that will work in Java 1.5. Also, I tried this (just to see what it looked like):
setHorizontalTextPosition(JLabel.CENTER);
And that also appears to break the repainting in exactly the same way. I looked through the source of our application and found other places where we set borders (including empty borders), but couldn't find any on JLabels (only panels, buttons, etc). Anybody see anything like this before? Know how to fix it? Or perhaps another way to obtain the spacing I require that may work around the bug? Thanks.
The problem is that you're calling that code inside the paint method. You should not do that because it will freeze the EDT with unwanted loops in the swing painting pipeline.
You should put that code on the constructor and change the component design state elsewhere on the app life cycle.
If you want to know a little bit more about Swing painting please read the "Swing painting pipeline" post on pushing-pixels.org.
Note that you can use BorderFactory.createCompoundBorder to combine any two borders. Then you can set spacing with the emptyBorder and any other to draw the outer border.
EDIT: Example added.
package com.stackoverflow.swing.paintpipeline;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.Border;
public class JLabelSetBorderPaintProblem extends JLabel {
public JLabelSetBorderPaintProblem(String text) {
super(text);
}
/*
* #see javax.swing.JComponent paint(java.awt.Graphics)
*/
#Override
public void paint(Graphics g) {
super.paint(g);
// You can not call setBorder here.
// Please check javadoc.
}
/*
* #see javax.swing.JComponent paintBorder(java.awt.Graphics)
*/
#Override
protected void paintBorder(Graphics g) {
super.paintBorder(g);
// Here is where the Swing painting pipeline draws the current border
// for the JLabel instance.
// Please check javadoc.
}
// Start me here!
public static void main(String[] args) {
// SetBorder will dispatch an event to Event Dispatcher Thread to draw the
// new border around the component - you must call setBorder inside EDT.
// Swing rule 1.
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() {
// Inside EDT
JFrame frame = new JFrame("JLabel setBorder example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Add the JLabel
final JLabelSetBorderPaintProblem label = new JLabelSetBorderPaintProblem("Just press or wait...");
frame.add(label);
// And change the border...
label.addMouseListener(new MouseAdapter() {
#Override public void mousePressed(MouseEvent e) {
label.setBorder(BORDERS.get(new Random().nextInt(BORDERS.size())));
}
});
// ...whenever you want
new Timer(5000, new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
label.setBorder(BORDERS.get(new Random().nextInt(BORDERS.size())));
}
}).start();
frame.pack();
frame.setVisible(true);
}
});
}
public static final List<Border> BORDERS;
static {
BORDERS = new ArrayList<Border>();
BORDERS.add(BorderFactory.createLineBorder(Color.BLACK));
BORDERS.add(BorderFactory.createLineBorder(Color.RED));
BORDERS.add(BorderFactory.createEtchedBorder());
BORDERS.add(BorderFactory.createTitledBorder("A border"));
}
}

Categories