I have a JButton which I want to set the background to a color.
JButton button = new JButton();
button.setVisible(true);
button.setPreferredSize(new Dimension(student_scroll.getWidth(), 50));
button.setBorder(BorderFactory.createLineBorder(Color.WHITE, 1));
button.setBackground(Color.BLACK);
button.setForeground(Color.WHITE);
button.setOpaque(true);
I used this for mac and it showed up as I wanted it to be. However, upon trying it on windows, the foreground is white(as it should) but the background is empty.
Setting background color to JButton
says to add button.setContentAreaFilled(false); which I did but had no effect. Most others say to add button.setOpaque(true);which I also did already.
What else do I have to do so that it will show up with a black background?
EDIT
As requested, the SSCCE:
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MainSwing extends JFrame {
private static final long serialVersionUID = -8231889836024827530L;
public static void main(String[] args) {
try {
System.setProperty("apple.laf.useScreenMenuBar", "true");
System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Test");
UIManager.put("ScrollBarUI", "main.CustomScrollBarUI");
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(ClassNotFoundException e) {
System.out.println("ClassNotFoundException: " + e.getMessage());
}
catch(InstantiationException e) {
System.out.println("InstantiationException: " + e.getMessage());
}
catch(IllegalAccessException e) {
System.out.println("IllegalAccessException: " + e.getMessage());
}
catch(UnsupportedLookAndFeelException e) {
System.out.println("UnsupportedLookAndFeelException: " + e.getMessage());
}
SwingUtilities.invokeLater( new Runnable() {
public void run() {
JFrame frame = new JFrame() {
Container c = getContentPane();
JButton button = new JButton("Hello");
{
button.setText("Hello");
button.setVisible(true);
button.setPreferredSize(new Dimension(100, 50));
button.setBorder(BorderFactory.createLineBorder(Color.WHITE, 1));
button.setBackground(Color.BLACK);
button.setForeground(Color.WHITE);
button.setOpaque(true);
c.add(button);
}
};
frame.setSize(500, 500);
frame.setBackground(Color.BLACK);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
It seems that the problem has something to do with the line: UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); as when I remove it, the buttons are black.
I'm guessing from those UIManager key/value pairs that the PLAF is the OS X based Aqua PLAF. And that seems to be part of the problem here. Here it is without the content area filled on Windows.
import java.awt.*;
import javax.swing.*;
public class MainSwing extends JFrame {
public static void main(String[] args) {
try {
System.setProperty("apple.laf.useScreenMenuBar", "true");
System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Test");
UIManager.put("ScrollBarUI", "main.CustomScrollBarUI");
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace(); // more info for less LOC!
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame() {
Container c = getContentPane();
JButton button = new JButton("Hello");
{
c.setLayout(new GridLayout(0,1));
c.add(new JButton("Hi"));
button.setText(UIManager.getSystemLookAndFeelClassName());
button.setVisible(true);
button.setPreferredSize(new Dimension(400, 100));
button.setBorder(BorderFactory.createLineBorder(Color.WHITE, 1));
button.setContentAreaFilled(false);
button.setBackground(Color.BLACK);
button.setForeground(Color.WHITE);
button.setOpaque(true);
c.add(button);
}
};
frame.pack();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
It seems that the problem has something to do with the line: UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); as when I remove it, the buttons are black.
So that is extra information we didn't have before you created the SSCCE (which is why you should always post a SSCCE with your question).
It also tells you the problem is not with your code but with the LAF. The Windows LAF ignores the setBackground(...) method and paints its own background.
One option would be to add an Icon to the button of your desired color. Then you can configure the text to be painted in the center of the button:
import java.awt.*;
import javax.swing.*;
public class ColorIcon implements Icon
{
private Color color;
private int width;
private int height;
public ColorIcon(Color color, int width, int height)
{
this.color = color;
this.width = width;
this.height = height;
}
public int getIconWidth()
{
return width;
}
public int getIconHeight()
{
return height;
}
public void paintIcon(Component c, Graphics g, int x, int y)
{
g.setColor(color);
g.fillRect(x, y, width, height);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI()
{
JPanel panel = new JPanel( new GridLayout(2, 2) );
for (int i = 0; i < 4; i++)
{
Icon icon = new ColorIcon(Color.RED, 50, 50);
JButton label = new JButton( icon );
label.setText("" + i);
label.setHorizontalTextPosition(JButton.CENTER);
label.setVerticalTextPosition(JButton.CENTER);
panel.add(label);
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(panel);
f.setSize(200, 200);
f.setLocationRelativeTo( null );
f.setVisible(true);
}
}
Then is should work on all LAF's.
Related
I am coding a GUI containing a JScrollPane that displays an image that gets updated (with potential modification of its dimensions). The image is in an ImageIcon in a JLabel. The image size is retrieved using ImageIcon.getIconWith() and getIconHeight(). And the JLabel preferred size is updated with those dimensions.
When the application is started for the first time, the JScrollPane and its scrollbars have the right dimensions to view the whole image (potentially using scrolling). But when the image gets updated the JScrollPane and the scrollbars assume the image has the dimensions of the previous image. How do I get the JScrollPane to update correctly ?
Here is a curated version of my GUI. Visualizer.java uses the GUI VisualizerGUI.java. When the "Run" button is pushed, a new image is randomly generated using ImageDrawer.drawImage() (simulates the behavior of the real application) and the content of the JScrollPane is updated using the function VisualizerGUI.setTransitionsImage(String imgPath).
Visualizer.java:
import java.util.*;
import java.io.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Visualizer implements ActionListener {
private VisualizerGUI gui = null;
public Visualizer() {
gui = VisualizerGUI.createAndStart(this);
}
public static void main(String[] args) {
Visualizer viz = new Visualizer();
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Run command")) {
run();
}
}
public void run() {
updateGUIwithSolution();
}
public void updateGUIwithSolution() {
gui.initGUIupdate();
try {
ImageDrawer.drawImage();
gui.setTransitionsImage("image.png");
} catch (Exception e) {
System.out.println("Error while generating image");
e.printStackTrace();
}
gui.finalizeGUIupdate();
}
}
VisualizerGUI.java:
import java.util.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.ActionListener;
import javax.swing.*;
import java.lang.reflect.InvocationTargetException;
public final class VisualizerGUI {
private JFrame frame;
private JButton runButton;
private JButton nextButton;
private JScrollPane transitionsDisplay;
private JTabbedPane executionsDisplay;
private JTabbedPane tracesDisplay;
private JTextArea textInfoArea;
public VisualizerGUI() {}
private void initGUI(ActionListener actionsHandler) {
//Create and set up the window.
frame = new JFrame("Visualizer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel controlPanel = new JPanel(new FlowLayout());
runButton = new JButton("Run");
runButton.addActionListener(actionsHandler);
runButton.setActionCommand("Run command");
controlPanel.add(runButton);
nextButton = new JButton("Next");
nextButton.addActionListener(actionsHandler);
nextButton.setActionCommand("Find next solution");
controlPanel.add(nextButton);
transitionsDisplay = new JScrollPane();
executionsDisplay = new JTabbedPane();
tracesDisplay = new JTabbedPane();
JSplitPane ETspliter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, executionsDisplay, tracesDisplay);
JSplitPane graphsSpliter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, transitionsDisplay, ETspliter);
textInfoArea = new JTextArea();
textInfoArea.setLineWrap(true);
textInfoArea.setWrapStyleWord(true);
textInfoArea.setEditable(false);
JScrollPane textInfoAreaSP = new JScrollPane(textInfoArea);
JSplitPane topSpliter = new JSplitPane(JSplitPane.VERTICAL_SPLIT, graphsSpliter, textInfoAreaSP);
transitionsDisplay.setPreferredSize(new Dimension(200,200));
executionsDisplay.setPreferredSize(new Dimension(200,200));
tracesDisplay.setPreferredSize(new Dimension(200,200));
textInfoAreaSP.setPreferredSize(new Dimension(200,100));
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(controlPanel, BorderLayout.NORTH);
frame.getContentPane().add(topSpliter, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public static VisualizerGUI createAndStart(ActionListener actionsHandler) {
VisualizerGUI gui = new VisualizerGUI();
final Runnable guiRunner =
new Runnable() {
public void run() {
gui.initGUI(actionsHandler);
// gui.pack();
}
};
try {
javax.swing.SwingUtilities.invokeAndWait(guiRunner);
} catch (InterruptedException e) {
System.out.println(">>> WARNING <<< InterruptedException while creating the GUI");
} catch (InvocationTargetException e) {
System.out.println(">>> WARNING <<< InvocationTargetException while creating the GUI");
}
return gui;
}
public void clear() {
initGUIupdate();
finalizeGUIupdate();
}
public void initGUIupdate() {
// frame.setVisible(false);
transitionsDisplay.setViewportView(null);
executionsDisplay.removeAll();
tracesDisplay.removeAll();
textInfoArea.setText(null);
}
public void pack() {
frame.pack();
}
public void finalizeGUIupdate() {
// frame.validate();
// frame.repaint();
// frame.setVisible(true);
}
public void setTransitionsImage(String imgPath) {
ImageIcon icon = new ImageIcon(imgPath);
icon.getImage().flush();
int width = icon.getIconWidth();
int height = icon.getIconHeight();
JLabel label = new JLabel();
label.setVerticalAlignment(SwingConstants.CENTER);
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setIcon(icon);
label.setPreferredSize(new Dimension(width,height));
//label.setPreferredSize(null);
transitionsDisplay.setViewportView(label);
label.revalidate();
label.repaint();
transitionsDisplay.getViewport().revalidate();
transitionsDisplay.getViewport().repaint();
transitionsDisplay.revalidate();
// transitionsDisplay.validate();
transitionsDisplay.repaint();
frame.revalidate();
// frame.validate();
frame.repaint();
}
public void setTransitionsImageInED(String imgPath) {
final Runnable guiRunner =
new Runnable() {
public void run() { setTransitionsImage(imgPath); }
};
// javax.swing.SwingUtilities.invokeLater(guiRunner);
try {
javax.swing.SwingUtilities.invokeAndWait(guiRunner);
} catch (InterruptedException e) {
System.out.println(">>> WARNING <<< InterruptedException while creating the GUI");
} catch (InvocationTargetException e) {
System.out.println(">>> WARNING <<< InvocationTargetException while creating the GUI");
}
}
}
ImageDrawer.java:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageDrawer {
public static void drawImage() throws Exception {
try {
int width = 20 + (int)(Math.random() * 1000);
int height = 20 + (int)(Math.random() * 1000);
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D ig2 = bi.createGraphics();
ig2.setPaint(Color.blue);
ig2.fillRect(0, 0, width, height);
ig2.setPaint(Color.red);
ig2.fillRect(5, 5, width - 10, height - 10);
ig2.setPaint(Color.blue);
ig2.drawLine(0, 0, width, height);
ig2.drawLine(0, height, width, 0);
ImageIO.write(bi, "PNG", new File("image.png"));
} catch (IOException ie) {
ie.printStackTrace();
}
}
}
Can someone explain why I have this problem? Thanks!
transitionsDisplay.setPreferredSize(new Dimension(200,200));
executionsDisplay.setPreferredSize(new Dimension(200,200));
tracesDisplay.setPreferredSize(new Dimension(200,200));
textInfoAreaSP.setPreferredSize(new Dimension(200,100));
Don't use setPreferredSize(...). Each Swing component is responsible for determining its own size.
The image size is retrieved using ImageIcon.getIconWith() and getIconHeight(). And the JLabel preferred size is updated with those dimensions.
Not necessary. Again the JLabel will determine its own size based on the size of the Icon. This is done dynamically as the image/icon changes.
The scrollbars of the scrollpane will appear when the preferred size of the label is greater than the size of the scrollpane. Just let the layout managers do their job.
I'm trying to have a JPanel of varying size (potentially much wider than the standard screen) inside of a JScrollPanel. Currently it works out great, and I have configured the scrollbars to work fine manually, however I would like the JPanel to "scroll" constantly to the left, so that over time the whole thing is displayed. All of the answers I found are specific to JTextArea and use Carets, or use rectToVisible. Neither of these will work because I'm trying to scroll internally to a single JPanel.
I've included what I believe to be all of the relevant code below.
center is the JPanel (of which Grid is a subclass, used to paint specifically a grid with some specific cells colored) with a BorderLayout that I would like to autoscroll.
public GuiViewFrame(Song playMe) {
String[][] songArray = playMe.to2DArray();
this.displayPanel = new ConcreteGuiViewPanel(playMe);
main = new JPanel();
main.setLayout(new BorderLayout());
displayPanel.setLayout(new BorderLayout());
center = new Grid(playMe);
labels = new Labels(playMe);
horiz = new Horiz(playMe);
center.setPreferredSize(new Dimension(10 * songArray.length, 10 * songArray[0].length));
horiz.setPreferredSize(new Dimension(10 * songArray.length, 10));
horiz.setVisible(true);
main.add(center, BorderLayout.CENTER);
main.add(horiz, BorderLayout.NORTH);
scroll = new JScrollPane(main,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
add(scroll, BorderLayout.CENTER);
labels.setPreferredSize(new Dimension(20, 10 * songArray[0].length));
labels.setVisible(true);
add(labels, BorderLayout.WEST);
JScrollBar horiz = scroll.getHorizontalScrollBar();
InputMap im = horiz.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke("RIGHT"), "positiveUnitIncrement");
im.put(KeyStroke.getKeyStroke("LEFT"), "negativeUnitIncrement");
im.put(KeyStroke.getKeyStroke("HOME"), "minScroll");
im.put(KeyStroke.getKeyStroke("END"), "maxScroll");
this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
this.pack();
}
The project as a whole is to generate a view for playing music that combines MIDI and a GUI, but right now once MIDI plays enough of the song, the relevant notes are off screen. I would like to scroll at a rate to keep pace with MIDI.
You can set the value of the horizontal scrollbar to control what is currently visible:
JScrollBar horizontal = scroll.getHorizontalScrollBar();
horizontal.setValue( horizontal.getValue() + ??? );
You would need to use a Swing Timer to schedule the scrolling at an appropriate interval.
Simple example of using a Timer to scroll text:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class TimerTest extends JPanel implements ActionListener
{
JLabel timeLabel;
JLabel scrollLabel;
public TimerTest()
{
setLayout( new BorderLayout() );
timeLabel = new JLabel( new Date().toString() );
add(timeLabel, BorderLayout.NORTH);
scrollLabel = new JLabel( "Some continuously scrolling text!! " );
add(scrollLabel, BorderLayout.SOUTH);
int time = 1000;
javax.swing.Timer timer = new javax.swing.Timer(time, this);
timer.setInitialDelay(1);
timer.start();
}
public void actionPerformed(ActionEvent e)
{
timeLabel.setText( new Date().toString() );
String oldText = scrollLabel.getText();
// Scroll right to left
String newText = oldText.substring(1) + oldText.substring(0, 1);
// Scroll left to right
// int length = oldText.length();
// String newText = oldText.substring(length-1, length)
// + oldText.substring(0, length-1);
scrollLabel.setText( newText );
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new TimerTest() );
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
One possible solution might be to take advantage of JComponent#scrollRectToVisible and a Swing Timer
For example...
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.Scrollable;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ScrollTest {
public static void main(String[] args) {
new ScrollTest();
}
public ScrollTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(new TestPane()));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel implements Scrollable {
public TestPane() {
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JViewport viewport = (JViewport) getParent();
Rectangle viewRect = viewport.getViewRect();
if (viewRect.x + viewRect.width < getWidth()) {
viewRect.x += 2;
scrollRectToVisible(viewRect);
} else {
((Timer)e.getSource()).stop();
}
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(1000, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawLine(0, 0, getWidth(), getHeight());
g2d.dispose();
}
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 64;
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 64;
}
#Override
public boolean getScrollableTracksViewportWidth() {
return getPreferredSize().width <= getParent().getSize().width;
}
#Override
public boolean getScrollableTracksViewportHeight() {
return getPreferredSize().height <= getParent().getSize().height;
}
}
}
I have a program that is basically just supposed to change the text of a label when your cursor enters a polygon that is shown on the JPanel. I have tried a few different things with nothing working. Currently I am trying an if statement to make it choose which button to add but it still doesn't change if i move my cursor into the polygon. when the cursor is outside of the polygon the label should say "point is not in the polygon" and when inside it should say "point is in the polygon". Any help would be greatly appreciated.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Chapter3Lab1 extends JFrame{
private RegularPolygonPanel canvas = new RegularPolygonPanel();
public Chapter3Lab1()
{
JPanel panel = new JPanel();
add(canvas, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
canvas.setFocusable(true);
canvas.requestFocusInWindow();
}
public static void main (String[] args)
{
String isInside = "The point is in the polygon";
String notInside = "The point is not in the polygon";
//Create a Polygon object
Polygon polygon = new Polygon();
polygon.addPoint(40,20);
polygon.addPoint(70,40);
polygon.addPoint(60,80);
polygon.addPoint(45,45);
polygon.addPoint(20,60);
JLabel label = new JLabel(isInside, JLabel.CENTER);
JLabel notlabel = new JLabel(notInside, JLabel.CENTER);
Chapter3Lab1 frame = new Chapter3Lab1();;
frame.setTitle("Chapter 3 Lab 1");
frame.setLayout(new FlowLayout());
frame.setLocationRelativeTo(null);// Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200,200);
while (true)
{
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
int x = (int) b.getX();
int y = (int) b.getY();
if(polygon.contains(x, y) == false)
{
frame.remove(label);
frame.add(notlabel);
}
else
{
frame.remove(notlabel);
frame.add(label);
}
frame.setVisible(true);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
class RegularPolygonPanel extends JPanel
{
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
//Create a Polygon object
Polygon polygon = new Polygon();
polygon.addPoint(40,20);
polygon.addPoint(70,40);
polygon.addPoint(60,80);
polygon.addPoint(45,45);
polygon.addPoint(20,60);
//Draw the polygon
g.drawPolygon(polygon);
}
public Dimension getPreferredSize()
{
return new Dimension(200,200);
}
}
}
Start by taking a look at How to Write a Mouse Listener
You will need to maintain a reference to the Polygon object and make use of it's contains method to determine if the mouse is within the Polygon itself...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private RegularPolygonPanel polyPanel;
private JLabel label;
public TestPane() {
polyPanel = new RegularPolygonPanel();
polyPanel.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
if (polyPanel.isWithinPolygon(e.getPoint())) {
label.setText("Is inside");
} else {
label.setText("Is outside");
}
}
});
label = new JLabel("...");
setLayout(new BorderLayout());
add(polyPanel);
add(label, BorderLayout.SOUTH);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
class RegularPolygonPanel extends JPanel {
private Polygon polygon;
public RegularPolygonPanel() {
//Create a Polygon object
polygon = new Polygon();
polygon.addPoint(40, 20);
polygon.addPoint(70, 40);
polygon.addPoint(60, 80);
polygon.addPoint(45, 45);
polygon.addPoint(20, 60);
}
public boolean isWithinPolygon(Point p) {
return polygon.contains(p);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//Draw the polygon
g.drawPolygon(polygon);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
The image isn't being painted when this is run with WordGen, how do i fix this?
When I run this without wordgen I can get the image to appear. I'm not sure what i'm doing wrong since i'm not getting any errors.
Any help is appreciated.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class tfot extends JComponent{
private static final long serialVersionUID = 1L;
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
showGUI(args);
}
});
}
public static void showGUI(String[] args) {
JPanel displayPanel = new JPanel();
JButton okButton = new JButton("Did You Know?");
okButton.setFont(new Font("Times", Font.TRUETYPE_FONT, 100));
final JLabel jLab = new JLabel();
okButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
jLab.setText(wordGen());
}
});
JPanel content = new JPanel();
content.setLayout(new BorderLayout());
content.add(displayPanel, BorderLayout.CENTER);
content.add(okButton, BorderLayout.SOUTH);
content.add(jLab, BorderLayout.NORTH);
JFrame window = new JFrame("Window");
window.setContentPane(content);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(800, 600);
window.setLocation(400, 300);
window.setVisible(true);
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawImage(Toolkit.getDefaultToolkit().getImage("Pictures/background1.png"), 0, 0, this);
}
public static String wordGen() {
String[] wordListOne = {"generic text","hi",};
int oneLength = wordListOne.length;
int rand1 = (int) (Math.random() * oneLength);
String phrase = wordListOne[rand1] + " ";
return phrase;
}
}
First...
Don't load resources or perform long running tasks within the paint methods, these may be called a number of times in quick succession. Instead, load the images before hand and paint them as needed...
public Tfot() {
setLayout(new BorderLayout());
try {
background = ImageIO.read(new File("pictures/background1.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
g.drawImage(background, 0, 0, this);
}
}
Generally, you are discouraged from overriding paint and instead should use paintComponent, lots of reasons, but generally, this is where the background is painted...
Second...
You need to add Tfot to something that is displayable, otherwise it will never be painted
JFrame window = new JFrame("Window");
window.setContentPane(new Tfot());
window.add(content);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(800, 600);
window.setLocation(400, 300);
window.setVisible(true);
Thrid...
JPanel by default is not transparent, you need to set it's opaque property to false
JPanel displayPanel = new JPanel();
displayPanel.setOpaque(false);
//...
JPanel content = new JPanel();
content.setOpaque(false);
Then it will allow what ever is below it to show up (ie, the background image)
Take a look at Painting in AWT and Swing, Performing Custom Painting and Reading/Loading an Image for more details
Fourth...
You need to learn the language basics for embarking on advance topics like GUI and custom painting, without this basic knowledge, this topics will bite you hard.
You need to declare background as a instance field of the class Tfot
private BufferedImage background;
public Tfot() {
Updated - Fully runnable example
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Tfot extends JComponent {
private static final long serialVersionUID = 1L;
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
showGUI(args);
}
});
}
public static void showGUI(String[] args) {
JPanel displayPanel = new JPanel();
displayPanel.setOpaque(false);
JButton okButton = new JButton("Did You Know?");
okButton.setFont(new Font("Times", Font.TRUETYPE_FONT, 100));
final JLabel jLab = new JLabel();
okButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
jLab.setText(wordGen());
}
});
JPanel content = new JPanel();
content.setOpaque(false);
content.setLayout(new BorderLayout());
content.add(displayPanel, BorderLayout.CENTER);
content.add(okButton, BorderLayout.SOUTH);
content.add(jLab, BorderLayout.NORTH);
Tfot tfot = new Tfot();
tfot.setLayout(new BorderLayout());
tfot.add(content);
JFrame window = new JFrame("Window");
window.setContentPane(tfot);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(800, 600);
window.setLocation(400, 300);
window.setVisible(true);
}
private BufferedImage background;
public Tfot() {
try {
background = ImageIO.read(new File("Pictures/background1.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(background, 0, 0, this);
}
public static String wordGen() {
String[] wordListOne = {"generic text", "hi",};
int oneLength = wordListOne.length;
int rand1 = (int) (Math.random() * oneLength);
String phrase = wordListOne[rand1] + " ";
return phrase;
}
}
I have this application that I am working on, I have a JFrame that uses a BorderLayout. In the JFrame is a JPanel, the JPanel is using a MigLayout.I am trying to make a JButton stay on the bottom left hand side of the screen , achieving a similar effect as the "position:fixed" property in CSS.
Any tips on how I can achieve this effect by code?
Tried JLayeredPane code from a few other sources, but still doesn't work somehow.
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if (info.getName().equals("Nimbus")) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
MainFrame frame = new MainFrame();
ForumMainPage panel = new ForumMainPage(frame);
panel.setFocusable(true);
panel.requestFocusInWindow();
frame.add(jLabelOnJButton());
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public MainFrame() {
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension dim = tk.getScreenSize();
this.setSize(dim);
this.setUndecorated(true);
this.setExtendedState(Frame.MAXIMIZED_BOTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new BorderLayout());
this.add(jLabelOnJButton(),BorderLayout.CENTER);
}
private static JComponent jLabelOnJButton(){
JLayeredPane layers = new JLayeredPane();
JLabel label = new JLabel("label");
JButton button = new JButton("button");
label.setBounds(40, 20, 100, 50);
button.setBounds(100, 20, 150, 75);
layers.add(label, new Integer(200));
layers.add(button, new Integer(100));
return layers;
}
}
Thanks in advance!
You could add the button to the frame's glass pane. This takes a little bit of work to make happen, as you need to keep track of the scroll pane relative to the glass pane, but it should achieve the desired effect
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class OverlayButton {
public static void main(String[] args) {
new OverlayButton();
}
public OverlayButton() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JScrollPane sp;
private JButton btn;
private JTextArea ta;
private JPanel glassPane;
public TestPane() {
setLayout(new BorderLayout());
btn = new JButton("Print");
ta = new JTextArea(10, 20);
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(new File("Script.txt")));
String text = null;
while ((text = br.readLine()) != null) {
ta.append(text + "\n");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (Exception e) {
}
}
ta.setCaretPosition(0);
sp = new JScrollPane(ta);
glassPane = new JPanel() {
#Override
public void doLayout() {
Point p = sp.getLocation();
Dimension dim = sp.getSize();
p = SwingUtilities.convertPoint(sp, p, this);
btn.setSize(btn.getPreferredSize());
int barWidth = sp.getVerticalScrollBar().getWidth();
int barHeight = sp.getHorizontalScrollBar().getHeight();
int x = p.x + (dim.width - btn.getWidth()) - barWidth;
int y = p.y + (dim.height - btn.getHeight()) - barHeight;
btn.setLocation(x, y);
}
};
glassPane.setOpaque(false);
glassPane.add(btn);
glassPane.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
e.getComponent().doLayout();
}
});
add(sp);
}
#Override
public void addNotify() {
super.addNotify();
SwingUtilities.getRootPane(this).setGlassPane(glassPane);
glassPane.setVisible(true);
glassPane.revalidate();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
}
Take a look at How to use Root Panes for more details
Try using the OverlayLayout:
JPanel contentPane = new JPanel();
contentPane.setLayout( new OverlayLayout(ContentPane) );
frame.setContentPane( panel );
JButton button = new JButton(...);
button.setAlignmentX(0.0f);
button.setAlignmentY(1.0f);
contentPane.add( button );
ForumMainPage panel = new ForumMainPage(frame);
contentPane.add( panel );