I've implemented a JFrame with 25 JButton components to represent the available rooms in a hotel. I do know this is not the whole program but how can I create a method in which when pressed the color changes?
The colors for available rooms is green and I would like to change them to red.
This code uses a JToggleButton with different colored icons for standard & selected states. A JCheckBox might also be used.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.*;
import java.util.*;
public class RoomReservationToggle {
private JComponent ui = null;
private String reservedPath = "https://i.stack.imgur.com/xj49g.png";
private String freePath = "https://i.stack.imgur.com/zJ8am.png";
RoomReservationToggle() {
try {
initUI();
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
}
public void initUI() throws MalformedURLException {
if (ui != null) {
return;
}
ui = new JPanel(new GridLayout(0, 4, 4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
ImageIcon reservedIcon = new ImageIcon(new URL(reservedPath));
ImageIcon freeIcon = new ImageIcon(new URL(freePath));
Random r = new Random();
for (int ii = 1; ii < 17; ii++) {
// a JCheckBox might also be used
JToggleButton tb = new JToggleButton(freeIcon, r.nextBoolean());
tb.setSelectedIcon(reservedIcon);
ui.add(tb);
}
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
RoomReservationToggle o = new RoomReservationToggle();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
You can use the methods setForeground() and setBackground() to change colours.
Make sure you call these methods from the event thread/queue.
Your configured L&F can ignore these however. Sometimes calling setOpaque(true) might help in those cases.
Related
I am trying to make an A* Pathfinding Visualizer but right now I am stuck on creating the grid. What is the best way of creating a grid like what is seen below? For instance, should I just use a bunch of JButton components or is there some other way?
Put JButton components in a GridLayout, using removeAll() on the panel before setting a new grid layout to change the number of columns and/or rows. Lastly pack() the top level container (in this case a JFrame) to fit the number of rows and columns.
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.EmptyBorder;
public class ChangableButtonGrid {
private JComponent ui = null;
JPanel gridArea = new JPanel();
public static final int SIZE = 600;
JToolBar tools = new JToolBar("Tools");
SpinnerNumberModel colModel = new SpinnerNumberModel(20, 5, 50, 1);
SpinnerNumberModel rowModel = new SpinnerNumberModel(5, 5, 50, 1);
ChangeListener changeListener = (ChangeEvent e) -> {
refresh();
};
public ChangableButtonGrid() {
initUI();
}
public final void initUI() {
if (ui!=null) return;
ui = new JPanel(new BorderLayout(4,4));
ui.setBorder(new EmptyBorder(4,4,4,4));
ui.add(gridArea);
ui.add(tools,BorderLayout.PAGE_START);
tools.setLayout(new FlowLayout(FlowLayout.LEADING));
addModelToToolbar("Cols", colModel);
addModelToToolbar("Rows", rowModel);
ui.add(gridArea);
}
private void refresh() {
int cols = colModel.getNumber().intValue();
int rows = rowModel.getNumber().intValue();
gridArea.removeAll();
gridArea.setLayout(new GridLayout(rows, cols));
for (int rr=0; rr<rows; rr++) {
for (int cc=0; cc<cols; cc++) {
JButton b = new JButton(cc + "," + rr);
gridArea.add(b);
}
}
Container c = gridArea.getTopLevelAncestor();
JFrame f = (JFrame)c;
f.pack();
}
private void addModelToToolbar(String label, SpinnerNumberModel model) {
tools.add(new JLabel(label));
JSpinner spinner = new JSpinner(model);
spinner.addChangeListener(changeListener);
tools.add(spinner);
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
ex.printStackTrace();
}
ChangableButtonGrid o = new ChangableButtonGrid();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
o.refresh();
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}
I have a grid with data and a JComboBox with a lot of users in it, of which one is selected. I would like to scroll to the selected item to the area where user can't see the rest of the data(the bottom of the grid) so that my JScrollPane will jump to this area automatically.
How can I do that?
I think this has something to do with scrollRectToVisible() method.
A JComboBox needs no JScrollPane.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class OneLineCombo {
private JComponent ui = null;
OneLineCombo() {
initUI();
}
public void initUI() {
if (ui!=null) return;
ui = new JPanel(new BorderLayout(4,4));
ui.setBorder(new EmptyBorder(4,20,4,20));
String[] fontFamily = GraphicsEnvironment.
getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
JComboBox fontCombo = new JComboBox(fontFamily);
fontCombo.setMaximumRowCount(1);
ui.add(fontCombo, BorderLayout.PAGE_START);
ui.add(new JLabel("Type some letters of the font name to select it"),
BorderLayout.PAGE_END);
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
OneLineCombo o = new OneLineCombo();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
I'm changing a cursor, using a PNG image (with transparency), but when I run the code below, the image doesn't look like it should.
public void CustomCursor()
{
Toolkit t1 = Toolkit.getDefaultToolkit();
Image img = t1.getImage("src/AppImages/Cursor1.png");
Point point = new Point(0,0);
Cursor cursor = t1.createCustomCursor(img, point, "Cursor");
setCursor(cursor);
}
This method is called in the Jframe's constructor.
This is the cursor1.png image, sized 25x25px.
After running the code:
If I use cursor1.png as a JLabel, it looks OK:
MCVE
import java.awt.*;
import java.net.*;
import java.util.logging.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class CustomCursor {
private JComponent ui = null;
CustomCursor() {
initUI();
}
public void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(20, 200, 20, 200));
Toolkit t1 = Toolkit.getDefaultToolkit();
Image img;
try {
URL url = new URL("http://i.stack.imgur.com/sJKuE.png");
img = t1.getImage(url);
Point point = new Point(0, 0);
Cursor cursor = t1.createCustomCursor(img, point, "Cursor");
ui.setCursor(cursor);
ui.add(new JLabel(new ImageIcon(url)));
} catch (MalformedURLException ex) {
Logger.getLogger(CustomCursor.class.getName()).log(Level.SEVERE, null, ex);
}
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
CustomCursor o = new CustomCursor();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
Can anyone tell why that happens?
The issue is Windows; transparent pixels just aren't taken into account.
There is a really good answer on how to fix this on this post.
Another good answer here.
I don't know the name of this type of menu, but I want to add an item to this kind of menu.
Follow the link for an example of the menu: Link: http://postimg.org/image/7izr3zapl/full/
IntelliJ IDEA has implemented this for Windows and OS X, so you could use it as an example.
Focusing on Windows here, you can take a look at the
RecentTasks class for the implementation. To add the recent tasks, the addTasksNativeForCategory native method gets called. This C++ method is implemented in the following file: jumplistbridge.cpp.
Those are menu items with icons. They are not buttons!
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.URL;
import javax.imageio.ImageIO;
public class MenuWithIcon {
private JComponent ui = null;
String[] urlStrings = {
"http://i.stack.imgur.com/gJmeJ.png",
"http://i.stack.imgur.com/gYxHm.png",
"http://i.stack.imgur.com/F0JHK.png"
};
String[] menuNames = {
"Blue Circle", "Green Triangle", "Red Square"
};
MenuWithIcon() {
initUI();
}
public void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
Image img = new BufferedImage(300, 150, BufferedImage.TYPE_INT_ARGB);
ui.add(new JLabel(new ImageIcon(img)));
}
public JMenuBar getMenuBar() throws Exception {
JMenuBar mb = new JMenuBar();
JMenu menu = new JMenu("Menu");
mb.add(menu);
for (int i=0; i<urlStrings.length; i++) {
URL url = new URL(urlStrings[i]);
Image img = ImageIO.read(url);
JMenuItem mi = new JMenuItem(menuNames[i], new ImageIcon(img));
menu.add(mi);
}
return mb;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
MenuWithIcon o = new MenuWithIcon();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
try {
f.setJMenuBar(o.getMenuBar());
} catch (Exception ex) {
ex.printStackTrace();
}
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
I am trying to do have two button in JFrame, and I call the setBounds method of them for setting the positions and size of them and also I passed null to setLayout1 because I want to usesetBounds` method of component.
Now I want to do something with my code that whenever I resize the frame buttons decoration will change in a suitable form like below pictures:
I know it is possible to use create an object from JPanel class and add buttons to it and at the end add created panel object to frame, but I am not allowed to it right now because of some reason (specified by professor).
Is there any way or do you have any suggestion?
My code is like this:
public class Responsive
{
public static void main(String[] args)
{
JFrame jFrame = new JFrame("Responsive JFrame");
jFrame.setLayout(null);
jFrame.setBounds(0,0,400,300);
JButton jButton1 = new JButton("button 1");
JButton jButton2 = new JButton("button 2");
jButton1.setBounds(50,50,100,100);
jButton2.setBounds(150,50,100,100);
jFrame.add(jButton1);
jFrame.add(jButton2);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setVisible(true);
}
}
A FlowLayout with no horizontal spacing, some vertical spacing and large borders could achieve that easily. A null layout manager is never the answer to a 'responsive' robust GUI.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class ResponsiveGUI {
private JComponent ui = null;
ResponsiveGUI() {
initUI();
}
public void initUI() {
if (ui!=null) return;
ui = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 8));
ui.setBorder(new EmptyBorder(10,40,10,40));
for (int i=1; i<3; i++) {
ui.add(getBigButton(i));
}
}
public JComponent getUI() {
return ui;
}
private final JButton getBigButton(int number) {
JButton b = new JButton("Button " + number);
int pad = 20;
b.setMargin(new Insets(pad, pad, pad, pad));
return b;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
ResponsiveGUI o = new ResponsiveGUI();
JFrame f = new JFrame("Responsive GUI");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
You could try to use:
jFrame.addComponentListener(new ComponentListener() {
// this method invokes each time you resize the frame
public void componentResized(ComponentEvent e) {
// your calculations on buttons
}
});