I have a JButton and a Point (it's motion controlled by leap motion) on the same JPanel.
However, they are overlapping with JButton on top.
Is there a way to have my Point always on top in the JPanel application window?
Here's a code snippet:
public leapPanel()
{
setLayout(null); //18-12-13
setBackground(Color.WHITE);
setVisible(true); //18-12-13
button = new JButton();
button.setBounds(100, 150, 100, 100);
button.setBackground(Color.BLACK);
add(button);
points[nPoints] = new Point(PWIDTH/2, PHEIGHT/2);
nPoints++;
listener = new leapListener(this);
controller = new Controller();
controller.addListener(listener);
}
public Dimension getPreferredSize()
{
return new Dimension(PWIDTH, PHEIGHT);
}
public void paintComponent(Graphics shape)
{
super.paintComponent(shape);
Graphics2D shaped = (Graphics2D)shape;
shaped.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for(int i=0; i<nPoints; i++)
{
shaped.setColor(Color.ORANGE);
shaped.fillOval(points[i].x, points[i].y, 12, 12);
}
}
private Point2D.Float calcScreenNorm(Hand hand, Screen screen)
/* The dot position is calculated using the screen position that the
user's hand is pointing at, which is then normalized to an (x,y)
value between -1 and 1, where (0,0) is the center of the screen.
*/
{
Vector palm = hand.palmPosition();
Vector direction = hand.direction();
Vector intersect = screen.intersect(palm, direction, true);
// intersection is in screen coordinates
// test for NaN (not-a-number) result of intersection
if (Float.isNaN(intersect.getX()) || Float.isNaN(intersect.getY()))
return null;
float xNorm = (Math.min(1, Math.max(0, intersect.getX())) - 0.5f)*2; // constrain to -1 -- 1
float yNorm = (Math.min(1, Math.max(0, (1-intersect.getY()))) - 0.5f)*2;
return new Point2D.Float(xNorm, yNorm);
} // end of calcScreenNorm()
I have a JButton and a Point (it's motion controlled by leap motion) on the same JPanel.
Not when components are on the same panel. The order of painting is to paint the component first (ie. your paintComponent() method is invoked). Then the child components of the panel are painted (ie. the button is painted). This is how Swing implements the parent/child relationship between components.
Try using two panels. The main panel will have a BorderLayout. Then you can use:
main.add(button, BorderLayout.NORTH);
main.add(leapPanel, BorderLayout.CENTER);
The other option is to try to use the OverlayLayout. It allows you to stack two components on top of one another, although I must admit I have problems controlling the exact location of components when using this layout. The basic code would be:
JPanel main = new JPanel();
main.setLayout( new OverlayLayout(main) );
JPanel buttonPanel = new JPanel();
buttonPanel.add( button );
main.add(buttonPanel);
main.add(leapPanel);
Using the OverlayLayout you may experience weird painting problems with the button. If so then check out the suggestion to override isOptimizedDrawingEnabled() from Overlap Layout.
JPanel main = new JPanel();
main.setLayout(new OverlayLayout(main));
//main.setBackground(Color.WHITE);
setSize(800, 600); //18-12-13
Container con = getContentPane();
con.setBackground(Color.WHITE);
BPanel = new buttonPanel();
panel = new leapPanel();
main.add(BPanel);
main.add(panel);
con.add(main);
This only allows me to show only BPanel on the application window.
What i need is to have both the point(panel) and button(BPanel) to be displayed on the application window with the point always on top.
Correct me if i am missing something here. Thanks!
Related
I am attempting to design a panel with MiGFormat that has a label at the top, and two buttons at the bottom - a yes/no prompt.
I achieve this closely, but the label yesOrNoText (text is "TEST") is not fully centered:
I initialize the panel containing this prompt like so:
private JPanel createYesNoPrompt() {
JPanel panel = new JPanel(new MigLayout());
panel.setBorder(BorderFactory.createLineBorder(Color.red));
JButton yesButton = new JButton("Yes");
JButton noButton = new JButton("No");
yesOrNoText = new JLabel();
yesOrNoText.setText("TEST");
yesOrNoText.setFont(panel.getFont().deriveFont(Font.BOLD, 30f));
yesOrNoText.setHorizontalAlignment(SwingConstants.CENTER);
Dimension dimension = new Dimension(500, 125);
Font font = panel.getFont().deriveFont(Font.BOLD, 20f);
yesButton.setFont(font);
yesButton.setBackground(new Color(35, 138, 35));
yesButton.setPreferredSize(dimension);
noButton.setFont(font);
noButton.setBackground(new Color(183, 19, 19));
noButton.setPreferredSize(dimension);
yesButton.addActionListener(e -> isYes = true);
noButton.addActionListener(e -> isYes = false);
panel.add(yesOrNoText, "wrap, dock center");
panel.add(yesButton);
panel.add(noButton);
return panel;
}
Then, I add it to gamePanel, then gamePanel to mainPanel, then mainPanel to the frame.
gamePanel.add(YesOrNoPanel, "align center");
mainPanel.add(gamePanel);
add(mainPanel);
I'm unsure of what would be causing yesOrNoText to not become fully centered within the YesNoPanel. Please let me know if I need to clarify anything!
Thank you.
I needed to make the add call for the yesNo label span 2 cells. By adding one component in the first row, then adding two in the next, I essentially created a 2x2 grid.
panel.add(yesOrNoText, "wrap, align center, span 2 1");
panel.add(yesButton);
panel.add(noButton);
Notice that on the first component I add yesOrNoText I use span to tell MiGFormat to take up two cells for this component. I can then center that with the remaining two components because it becomes the only component in the row.
I'm working on some nesting of GUI objects. I've gotten most of it working so far but the latest part I haven't been able to figure out. It may be a simple problem and I don't think the depth of nesting is causing the issue but I'll list what I have in case it is.
So far I have a JFrame containing a JPanel, which has a JTabbedPane, this JTabbedPane has 2 JPanels in it. I am currently working on one of these JPanels - it contains a JSplitPane containing a JScrollPane and another JSplitPane. The second JSplitPane has two JScrollPanes. One of the JScrollPanes has a JPanel.
This is all working correctly up until the last JPanel, I've added a background just as a means of testing it to see if it's working right. My problem is that the background shows up basically as a border within the JScrollPane, the inside of the pane is gray, like there is no background.
Here is some of my code - I can provide more if anybody thinks it would be useful.
This is the JPanel that is within the JTabbedPane.
public class MapEditor extends JPanel{
int height, width;
final int DIVIDER_SIZE = 7;
final int HORIZONTAL_DIVIDER_PLACE = 300;
final int VERTICAL_DIVIDER_PLACE = 200;
//side bar divider separates main page and left (vertical divider)
//side bar division separates top and bottom of sidebar (horizontal divider)
JSplitPane sideBarDivider;
JSplitPane sideBar;
//scroll pane to hold tiles panel, map panel
JScrollPane toolContainer;
JScrollPane tileContainer;
JScrollPane mapContainer;
//panels held inside JScrollPanes above
JPanel toolPanel;
JPanel tilePanel;
JPanel mapPanel;
public MapEditor(int w, int h){
this.width = w;
this.height = h;
setLayout(new BorderLayout());
//we can just pass the final variables in here because it's in the top left
toolPanel = new ToolPanel(HORIZONTAL_DIVIDER_PLACE,
VERTICAL_DIVIDER_PLACE);
sideBar = splitScreen();
add(sideBar);
}
//main split between map and tools/tiles
public JSplitPane splitScreen(){
mapContainer = new JScrollPane();
sideBar = buildSideBar();
//add map container and sidebar
sideBarDivider = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
sideBar, mapContainer);
sideBarDivider.setSize(width, height);
//set divider size and position
sideBarDivider.setDividerLocation(HORIZONTAL_DIVIDER_PLACE);
sideBarDivider.setDividerSize(DIVIDER_SIZE);
return sideBarDivider;
}
//small split between tools and tiles
public JSplitPane buildSideBar(){
toolContainer = new JScrollPane();
toolContainer.add(toolPanel);
tileContainer = new JScrollPane();
//add tile & tool containers
sideBar = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
toolContainer, tileContainer);
//set divider size and position
sideBar.setDividerSize(DIVIDER_SIZE);
sideBar.setDividerLocation(VERTICAL_DIVIDER_PLACE);
return sideBar;
}
}
This is the panel that is giving me problems.
public class ToolPanel extends JPanel{
int width, height;
public ToolPanel(int w, int h){
this.width = w;
this.height = h;
setLayout(new BorderLayout());
setSize(w, h);
setBackground(Color.BLACK);
}
}
Anybody see anything I'm doing wrong? I'm not too experienced with Java GUI components and would appreciate any help anybody has to offer.
toolContainer = new JScrollPane();
toolContainer.add(toolPanel);
You don't add components to a JScrollPane. The component is added to the "viewport" of the scroll pane.
You can use:
toolContainer = new JScrollPane( toolPanel );
or
toolContainer = new JScrollPane();
toolContainer.setViewportView(toolPanel);
Also, you should not be using:
setSize(w, h);
The layout manager of the component will determine the preferred size of the component based on the comopnents added to the panel.
If you are doing some kind of custom painting then you should override the getPreferredSize() method of the ToolPanel to return the appropriate size.
I am new to Swing. I am building a JFrame with a JScrollPane inside it using Eclipse IDE. Inside of the JScrollPane is a JPanel in Border Layout. I tried to add a JButton (called "submitAnswers") to the JFrame using the code below, but for some reason the button only appears at the end of the frame on my computer, but not on other computers (my friend tried it on his Mac and I tried it on a separate Windows OS like mine). Some proposed solutions that I have tried and from other sites that have not worked include:
Use the pack() method. Reason: since the preferred size of the JPanel is much longer in height than the JFrame (hence I employed a JScrollPane), packing the JFrame only causes the text to be not visible on the desktop.
Place button on content JPanel. Reason: I don't know. It just wouldn't appear on another desktop computer or my friend's mac computer.
Use BorderLayout.SOUTH instead of BorderLayout.PAGE_END. Reason: There was absolutely no change. The button would still be visible on my computer, but invisible on others.
Place button directly on JFrame. Reason: I don't know.
In addition, my JFrame is nested within a static method; hence, I've only included the relevant code for the specific method I'm having issues with.
Has anyone had this issue before? I would really appreciate your insight.
Code:
public static void createTestPage() {
JFrame testFrame = new JFrame("testing...1,2,3");
//Customizes icon to replace java icon
try {
testFrame.setIconImage(ImageIO.read(new File("src/icon.png")));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//Centers location of introFrame to center of desktop
Dimension screenDimensions = Toolkit.getDefaultToolkit().getScreenSize();
testFrame.setLocation(screenDimensions.width / 16,screenDimensions.height / 14);
//Size and display the introFrame.
Insets insets = testFrame.getInsets();
//Format size of screen itself
testFrame.setSize(1200 + insets.left + insets.right,
400 + insets.top + 250 + insets.bottom);
//Temporarily set screen so that it cannot be resized
testFrame.setResizable(false);
//Set background color of testFrame
testFrame.getContentPane().setBackground(new Color(75, 0, 130));
testFrame.setLayout(new BorderLayout());
//Set layout of testFrame
testFrame.setLayout(new BorderLayout(10, 1));
//Test content
JPanel testContentPanel = new JPanel();
testContentPanel.setBackground(new Color(75, 0, 130));
testContentPanel.setSize(new Dimension(900,2060));
testContentPanel.setPreferredSize(new Dimension(900, 2060));
//Test content pane layout
testContentPanel.setLayout(new BoxLayout(testContentPanel, BoxLayout.PAGE_AXIS));
//Create panel to hold instructions text
JPanel instructionsPanel = new JPanel();
instructionsPanel.setBackground(new Color(75, 0, 130));
instructionsPanel.setLayout(new BorderLayout(10,1));
//Create JPanel for submit answers button
JPanel submitAnswersPanel = new JPanel(new BorderLayout());
submitAnswersPanel.setBackground(new Color(75, 0, 130));
submitAnswersPanel.setVisible(true);
//Create button to submit personality test answers
JButton submitAnswers = new JButton("Submit Answers");
submitAnswers.setVisible(true);
submitAnswers.setBorder(new EmptyBorder(10, 400, 10, 400));
//Add submitAnswers button to panel
submitAnswersPanel.add(submitAnswers);
//Add submitAnswersPanel to test content panel
testContentPanel.add(submitAnswersPanel);
//Create scroll pane to allow for scrollable test (contents cannot fit one page)
JScrollPane testScrollPane = new JScrollPane();
testScrollPane.setViewportView(testContentPanel);
//Get rid of horizontal scroll bar and add vertical scrollbar
testScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
testScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
//Speed up scrolling
testScrollPane.getVerticalScrollBar().setUnitIncrement(16);
testFrame.add(testScrollPane);
//Experiment to show button
testFrame.setVisible(true);
}
I've refactored your code a little to use method to create the individual components of the GUI. You can find the full code at this ideone link
What I saw when I first copied your code to my machine was that the only thing visible was the button. So I create all the components in their own methods and then added them to the frame and panels using the Border Layout. This then enabled me to put the instructions in the NORTH sections, the button in the SOUTH section and then the main bits would go in the CENTER section.
One thing to note about the sections: (From the documentation)
The components are laid out according to their preferred sizes and the constraints of the container's size. The NORTH and SOUTH components may be stretched horizontally; the EAST and WEST components may be stretched vertically; the CENTER component may stretch both horizontally and vertically to fill any space left over.
So you should add the component you want to scale in size to the CENTER section.
My main method now looks like this:
public static void main(final String[] args) {
final JButton submitAnswers = createSubmitAnswersButton();
final JPanel instructionsPanel = createInstructionsPanel();
final JPanel testContentPanel = createContentPanel();
testContentPanel.add(instructionsPanel, BorderLayout.NORTH);
testContentPanel.add(submitAnswers, BorderLayout.SOUTH);
final JScrollPane scrollingContentPane = createScrollPaneFor(testContentPanel);
final JFrame testFrame = createJFrame();
testFrame.add(scrollingContentPane, BorderLayout.CENTER);
testFrame.setVisible(true);
}
I would like to create something like the following in Swing:
The top part is relatively easy: I can just create a table and display it. What I'm having trouble with is the square plus and minus buttons at the bottom, which are designed to add a new item or remove the selected item respectively. In particular, I haven't been able to make the square shape because on Mac OS X and some other platforms, JButtons are rectangles with rounded corners and I can't find a way to change that. Also, I'm wanting to make sure it's a perfect square and without any space in between buttons.
How can this be accomplished in a cross-platform way on Swing?
JButtons are rectangles with rounded corners and I can't find a way to change that.
Change the Border:
button.setBorder( new LineBorder(Color.BLACK) );
Edit.
Another approach is to create your own icon from an existing button. Something like the following:
JButton button = new JButton("+");
Dimension size = button.getPreferredSize();
size.x += 6;
size.y += 6;
button.setPreferredSize(size);
Rectangle rectangle = new Rectangle(3, 3, size.x - 3, size.y - 3);
ScreenImage buttonImage = ScreenImage(button, rectangle);
ImageIcon icon = new ImageIcon(buttonImage);
JButton plus = new JButton(icon);
plus.setBorder( ... );
The above code should create an image of your button on any platform. I increased the preferred size to avoid taking an image of the border.
You will need to use the Screen Image class.
This is most easily achieved by returning a preferred size that is NxN - where N is the larger of preferred width or height.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
class SquareButton extends JButton {
SquareButton(String s) {
super(s);
}
#Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
int s = (int)(d.getWidth()<d.getHeight() ? d.getHeight() : d.getWidth());
return new Dimension (s,s);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
JComponent gui = new JPanel(new FlowLayout());
for (int ii=0; ii<5; ii++) {
gui.add(new SquareButton("" + ii));
}
gui.setBorder(new EmptyBorder(4, 8, 4, 8));
JFrame f = new JFrame("Square Buttons");
f.add(gui);
// Ensures JVM closes after frame(s) closed and
// all non-daemon threads are finished
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// See http://stackoverflow.com/a/7143398/418556 for demo.
f.setLocationByPlatform(true);
// ensures the frame is the minimum size it needs to be
// in order display the components within it
f.pack();
// should be done last, to avoid flickering, moving,
// resizing artifacts.
f.setVisible(true);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}
You can set the size of a button using using setPreferredSize():
JButton button = new JButton("+");
button.setPreferredSize(new Dimension(10, 10));
You might be able to remove the rounded corners using:
button.setBorder(BorderFactory.createEmptyBorder());
If this does not work then you can override the paintComponent() method on JButton.
Well in order to make them square, you have 2 options: 1. Make the button hold an icon image of just a square image of a transparent image. 2. you could set the button dimensions on your own. I am not sure how to set the dimensions, but that is a an option you could choose. You can just create a JToolBar that is set on the BorderLayout.SOUTH end of the window whenever you add, and whatever buttons are added onto that, will be right next to each other. To add the buttons do this:
JButton button1 = new JButton("+");
JButton button2 = new JButton("-");
JToolBar toolbar = new JToolBar();
<JPanel,JFrame,Whatever>.add(toolbar, BorderLayout.SOUTH);
toolbar.add(button1);
toolbar.add(button2);
This will add the toolbar onto the JFrame, JPanel, or whatever you're adding it onto, and it will set it to the bottom of the screen as you see above.
Hope this helps!
I have written a code in java using swing, so that I will have a JscrollPane added to JPanel and then I will add buttons of fixed size to JPanel in vertical fashion
JPanel panel=new JPanel();
panel.setBackground(Color.WHITE);
int v=ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
int h=ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS;
JScrollPane jsp=new JScrollPane(panel,v,h);
jsp.setPreferredSize(new Dimension(600,600));
jsp.setBounds(150,670,850,200);
frame.add(jsp);
then I am adding buttons to it at run time.
for(i=0;i<n;i++)
{
button[i]=new JButton();
button[i].setBounds(20,y,120,120);
button[i].setSize(120,120);
button[i].setToolTipText(file[i].toString());
button[i].setIcon(Icon);
panel.add(button[i]);
y=y+140;
}
I want to add a buttons one below the other...(i.e I want a vertical scrollbar)
i.e. button1
button2
'
'
but above code is giving me buttons in a line (i.e. I am getting horizontal scrollbar)
i.e. button1 button2...
another problem is the size of the buttons. Using btn.setSize() is not affecting size at all...
can anybody help me?
You must use an appropriate Layoutmanager like GridLayout, Boxlayout or GridBagLayout for the panel.
It depends what else you want to put into the panel.
GridLayout is easier to use IMO:
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(0, 1)); // any number of rows, 1 column
...
panel.add(button[i]);
BoxLayout is almost as easy:
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
...
panel.add(button[i]);
GridBagLayout is more powerful, allowing more than one column, components spanning more than one cell, ... needs a GridBagConstraints to add the elements:
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints(
0, RELATIVE, // x = 0, y = below previous element
1, 1, // cell width = 1, cell height = 1
0.0, 0.0 // how to distribute space: weightx = 0.0, weighty = 0,0
GridBagConstraints.CENTER, // anchor
GridBagConstraints.BOTH, // fill
new Insets(0, 0, 0, 0), // cell insets
0, 0); // internal padding
...
panel.add(button[i], constraints);
Have a look at this tutorial: Laying Out Components Within a Container (The visual guide is a good start point)
EDIT:
you can also lay out the components by hand, that is, specify the location and size of each component in the container. For this you must set the LayoutManager to null so the default manager gets removed.
JPanel panel = new JPanel();
panel.setLayout(null);
...
button[i].setLocation(x, y);
button[i].setSize(width, heigth);
// OR button[i].setBounds(x, y, width, height);
panel.add(button[i]);
You need to define an appropriate LayoutManager for your JPanel, which is responsible for how the Components added to it are positioned. The default LayoutManager is FlowLayout, which lays out Components left-to-right. For laying out Components vertically you should consider using BoxLayout or GridBagLayout.
You have to set LayoutManager for JPanel or use Box(BoxLayout.Y_AXIS) instead.
For the size of buttons use preferredSize
For your layout problem you need to change the layout manager to one that does a vertical layout. For playing around purposes you can use BoxLayout like this:
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
This is much easier if you let the layout manager do its work.
In Swing, the way the components are layout over other component ( a panel for instance ) is using a layout manager.
It is used to avoid having to compute the coordinates of all the components against each other each time the container component resizes, or a new component is added.
There are different layout mangers, the one that you need here is BoxLayout.
By using this layout you don't need to specify the button position, nor its size. The layout manager query each component and use that information to place them in the correct position and size.
For instance the following frame
Was created this ( modified version of your ) code:
import javax.swing.*;
import java.awt.*;
public class ScrollTest {
private JPanel panel;
private Icon[] icons = new Icon[3];
public void main() {
panel =new JPanel();
// Use top to bottom layout in a column
panel.setLayout( new BoxLayout( panel, BoxLayout.Y_AXIS ));
panel.setBackground(Color.WHITE);
int v=ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
int h=ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS;
JScrollPane jsp=new JScrollPane(panel,v,h);
jsp.setPreferredSize(new Dimension(600,600));
jsp.setBounds(150,670,850,200);
JFrame frame = new JFrame();
frame.add(jsp);
// my addition to load sample icons
loadImages();
// simulate dynamic buttons
addButtons();
frame.pack();
frame.setVisible( true );
}
void loadImages() {
icons[0] = new ImageIcon( "a.png" );
icons[1] = new ImageIcon( "b.png" );
icons[2] = new ImageIcon( "c.png" );
}
void addButtons() {
for( int i = 0 ; i < icons.length ; i++ ) {
JButton button = new JButton();
Icon icon = icons[i];
button.setIcon( icon );
// Set the button size to be the same as the icon size
// The preferred size is used by the layout manager
// to know what the component "better" size is.
button.setPreferredSize( new Dimension( icon.getIconWidth(),
icon.getIconHeight() ) );
// This is IMPORTANT. The maximum size is used bythe layout manager
// to know "how big" could this component be.
button.setMaximumSize( button.getPreferredSize() );
panel.add( button );
}
}
public static void main( String ... args ) {
new ScrollTest().main();
}
}
I hope this helps.
One can also get a vertical scrolling for JPanel with SpringLayout. It's possible if panel's vertical size will be defined by setting a constraint SpringLayout.SOUTH. This can be done like this:
JPanel panel = new JPanel();
SpringLayout panelLayout = new SpringLayout();
panel.setLayout(panelLayout);
// Adding components to the panel here
// .....
// That's what defines panel's exact size and makes its scrolling possible
panelLayout.putConstraint(SpringLayout.SOUTH, panel, 0,
SpringLayout.SOUTH, lastComponentOfThePanel);
JScrollPane panelScrollPane = new JScrollPane(panel);
where lastComponentOfThePanel is a component at the bottom of a panel.
Hope this will help somebody. In my opinion, SpringLayout is very powerful layout manager, and sometimes it's very difficult or almost impossible to replace this one with GridBagLayout.
What about?
JScrollPane scrollPane = new JScrollPane(yourpanel);
container.add(scrollPane);