How to move 3 buttons inside a window - java

In the below code I am attempting to move the three buttons to the left when you click the left button. When I click it; nothing happens currently. Can anyone explain to me what I am doing wrong here? Also, for some reason it has stopped compiling correctly and I am unsure why but I BELIEVE it is because of a mistake in my code while attempting to get the buttons to move to the left when you click the button. I do NOT want the window to move. Just the buttons within the window. Does any one see what I am doing wrong and can you explain it?
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Buttons extends JFrame {
//Control Definitions
JButton resetButton;
JButton leftButton;
JButton colorButton;
JPanel buttonPanel;
// Layout Definiton
eventHandle evt;
FlowLayout flt;
Point point; //to Hold Previous Window Position
Color color; //to Hold Previous Color
public Buttons() {
super("Buttons Window");
flt = new FlowLayout();//inialize the Flow Layout
buttonPanel = new JPanel(flt);
//inialize the buttonPanel With Flow Layout
//initialize buttons
resetButton = new JButton("Reset");
leftButton = new JButton("Left");
colorButton = new JButton("Blue");
evt = new eventHandle(); //initiate the eventhandle class
buttonPanel.add(leftButton); //add leftButton
buttonPanel.add(colorButton);//add colorButton
buttonPanel.add(resetButton);//add colorButton
getContentPane().add(buttonPanel);//buttonPanel
//add actionlistners
leftButton.addActionListener(evt);
colorButton.addActionListener(evt);
resetButton.addActionListener(evt);
setBounds(20, 120, 250, 70);
//following Initate the point with Center of Scren
point = new Point((Toolkit.getDefaultToolkit().
getScreenSize().width - getWidth()) / 2,
(Toolkit.getDefaultToolkit().getScreenSize().height
- getHeight()) / 2);
setLocation(point); //locates the window in center
color = buttonPanel.getBackground();//stores the initial color
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
class eventHandle implements ActionListener { //Event Handler
public void actionPerformed(ActionEvent e) {
{
if (e.getSource() == leftButton) ///if its from leftButton
{
leftButton.setAlignmentX(Component.LEFT_ALIGNMENT);
colorButton.setAlignmentX(Component.LEFT_ALIGNMENT);
resetButton.setAlignmentX(Component.LEFT_ALIGNMENT);
//setLocation( (point.x -150), point.y);//shift the window 150 pixels left
} else if (e.getSource() == colorButton) {
buttonPanel.setBackground(color.BLUE);
//sets the backgorund to Blue
} else {
leftButton.setAlignmentX(Component.CENTER_ALIGNMENT);
//sets the location to previous location
colorButton.setAlignmentX(Component.CENTER_ALIGNMENT);
resetButton.setAlignmentX(Component.CENTER_ALIGNMENT);
}
}
}
}
public static void main(String[] args) {
Buttons buttonwindow = new Buttons();
}
}

It has stopped compiling, because you deleted one accolade, so put one accolade "}" just above the method:
public static void main(String[] args)
and the code should compile. pls feedback.
EDIT:
Also rewrite your main method like this:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Buttons buttonwindow = new Buttons();
}
}
);
}
Every usage of Swing components must be done thorugh the Event Dispatch Thread (abbreviated EDT) or you will probably get unwanted visual effects. See here for explanation.
EDIT^2:
To achieve the desired behavior, rewrite the the action listener like this:
if (e.getSource() == leftButton) {
((FlowLayout)buttonPanel.getLayout()).setAlignment(FlowLayout.LEFT); //1
buttonPanel.revalidate(); //2
}
else if (e.getSource() == colorButton) {
buttonPanel.setBackground(color.BLUE);
}
else {
((FlowLayout)buttonPanel.getLayout()).setAlignment(FlowLayout.CENTER);
buttonPanel.revalidate();
}
Any change to the visual appereance to the Swing component must be done through the assigned layout manager, in this case FlowLayout - in line 1.
To see the change you must notify the Swing components layout manager to rearrange the components - in line 2 the revalidate() method "notifies" the layout manager to recalculate the new positions and eventually "notifies" the EDT to draw it on the screen.

You should update the layout manager to align the components to the left or right. Try something like;
((FlowLayout)getLayout()).setAlignment(FlowLayout.LEFT);
Instead

You code won't compile as the static main method appears inside the inner class eventHandle. You can fix simply by moving it into the class body of the outer class Buttons.
As you have all the objects references at class level, you could do the button alignment using, for instance:
flt.setAlignment(FlowLayout.RIGHT);
buttonPanel.revalidate();
...
Here you are adjusting the layout alignment of your FlowLayout and revalidating to visually reflect the updated changes on your panel.

Related

Java Swing JScrollPane not scrolling when shift held down and using mouse wheel

I have a simple Java Swing program defined below:
import javax.swing.*;
import java.awt.*;
public class Test implements Runnable {
public static void main(String[] args) {
Test main = new Test();
SwingUtilities.invokeLater(main);
}
#Override
public void run() {
// Application window.
JFrame mainFrame = new JFrame();
// Set up window.
mainFrame.setPreferredSize(new Dimension(600,700));
mainFrame.setFocusable(true);
mainFrame.requestFocus();
JScrollPane scrollPane = new JScrollPane();
scrollPane.setPreferredSize(new Dimension(600,700));
JPanel scrollPanel = new JPanel();
scrollPanel.setLayout(new GridLayout(0,1));
// Add buttons.
for (int i = 0; i < 40; i ++) {
JButton button = new JButton("Button " + i);
button.setPreferredSize(new Dimension(600,100));
scrollPanel.add(button);
}
scrollPane.setViewportView(scrollPanel);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JPanel mainPanel = new JPanel();
mainPanel.add(scrollPane);
// Fill up window.
mainFrame.getContentPane().setLayout(new BorderLayout());
mainFrame.getContentPane().add(mainPanel, BorderLayout.CENTER);
SwingUtilities.updateComponentTreeUI(mainFrame);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.pack();
mainFrame.setVisible(true);
}
}
The program consists of a simple JScrollPane with multiple buttons inside of it. Only vertical scrolling is enabled. It works fine.
However, the problem is, when I am holding down the 'shift' key, vertical scrolling does not work when I am using the mouse wheel to scroll. Vertical scrolling only works when I drag the scrollbar or let go of the 'shift' key.
Usually, in a JScrollPane, when the 'shift' key is held down, and the mouse wheel is used, it scrolls horizontally instead of vertically. However, I have disabled horizontal scrolling.
How would I go about enabling vertical scrolling using the mouse wheel if the user is holding down 'shift'?
I don't think there is a simple way to do this because normally you would only need the shift scroll when scrolling in more than one direction.
You could try adding a key listener to your JFrame and setting the wheel on your mouse to scroll vertically whenever the shift key is pressed. I tried it with this code and it worked just fine:
frame.addKeyListener(new KeyListener() {
#Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
if(arg0.isShiftDown()) {
frame.addMouseWheelListener(new MouseWheelListener() {
#Override
public void mouseWheelMoved(MouseWheelEvent arg0) {
// TODO Auto-generated method stub
pane.getVerticalScrollBar().setValue(pane.getVerticalScrollBar().getValue()+arg0.getWheelRotation());
}
});
}
if(!arg0.isShiftDown()) {
frame.removeMouseWheelListener(frame.getMouseWheelListeners()[0]);
}
}
}
I have figured out a cleaner and simpler answer to my question. Here is the code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class CustomScrollPane extends JScrollPane {
public CustomScrollPane(Component component) {
super(component);
initialize();
}
private void initialize() {
// Set up the scroll bar.
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
// Disable scrolling so we can do it manually.
setWheelScrollingEnabled(false);
addMouseWheelListener(new MouseWheelListener() {
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
// Manually scroll.
getVerticalScrollBar().setValue(getVerticalScrollBar().getValue() + (e.getWheelRotation()));
}
});
}
}
The solution involves disabling JScrollPane from scrolling. It detects when the mousewheel is being rotated, and manually scrolls. This way, it will scroll when the mousewheel is rotated; it does not matter if 'shift' is being held down or not. The only drawback that I can see is that getVerticalScrollBar().setUnitIncrement() will not change the scrolling speed. The scrolling speed has to be changed manually, perhaps with a constant multiplier.

How to create a "Game Option/Pause Screen" in Swing?

Background: Making a game in Swing. It is simple turn base game. Not a whole lot going on. Because of this I didn't think I would need to implement a Game Tick. Rather, my thought was when a component got changed or needed to be updated just simply revalidate/repaint that component on the fly rather than repainting the whole screen.
I have a GameJPanel which currently has all the components on it. This JPanel is the one that contains the components that get revalidated/repainted etc.
I figured I could make JLayeredPane that holds GameJPanel and my OptionJPanel. Have a Button on GameJPanel that when pressed causes the OptionJPanel to show on top of it and having its JPanel 50% transparent (so it gives the affect it dims the GameJPanel).
However, once I did this what happened was that the GameJPanel started to replace OptionJPanel components (because of the events... etc; repainting of the components).
So currently I am at a loss on what to do. I'm thinking if I had some sort of game tick I wouldn't be having this issue, however, I am not 100% certain. I'm a little worried if I implemented a gametick that the events in game will cause the GameJPanel components to show through for half a second then get replaced. There are some events that cause components to repaint themselves without manually doing it (like quick example for JLabel setText();)
As an example of what I'm trying to go for.
I have tried with a CardLayout but I couldn't figure out how to have the OptionJPanel be on top of GameJPanel while seeing GameJPanel in the background (I tried setting background color, setOpaque(false)..., tried to limit Option JPanel size but I think the CardLayout stretches it (not 100% sure)) all I got was a gray background when doing so.
I would prefer not to go the CardLayout route because in the future I also plan on placing components on top of the GameJPanel (like someone clicks a button, have another panel on a different layer have a component slide in or out etc).
I use CardLayout a ton with my other components in GameJPanel to swap screens around, but haven't had the need to have the other components behind the one showing to show through.
Any ideas on how to go about this would be great or even example code that shows this.
As noted above, you would use a JDialog, a component that is easy to make (similar to making a JFrame) and easy to place. Simply place it "relative-to" the JFrame, e.g.,
myDialog.setLocationRelativeTo(myJFrame);
... and it will automatically center itself on the JFrame. The tricky part is dimming the underlying JFrame, and for this you would need to use a JGlassPane added to the JFrame's rootpane, one set with a background color that uses an alpha composite value. The tricky part with this is to draw the darker background without causing side effects, and to do this, please read Rob Camick's (StackOverflow user camickr) excellent tutorial on drawing in Swing with alpha composites which you can find here: Java Tips Weblog: Backgrounds with Transparency
An example of such a program is shown here:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class DialogEg {
// path to example image used as "game" background
private static final String IMG_PATH = "https://upload.wikimedia.org/"
+ "wikipedia/commons/7/76/Jump_%27n_Bump.png";
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
// get the "game" background image, or exit if fail
BufferedImage img = null;
try {
URL imgUrl = new URL(IMG_PATH);
img = ImageIO.read(imgUrl);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
// pass "game" image into main JPanel so that it will be drawn
DeMainPanel mainPanel = new DeMainPanel(img);
JFrame frame = new JFrame("Dialog Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel); // add main JPanel to JFrame
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
// main JPanel
#SuppressWarnings("serial")
class DeMainPanel extends JPanel {
private BufferedImage img; // background image
// JButton action that shows the JDialog and darkens the glasspane
private PauseAction pauseAction = new PauseAction("Pause");
public DeMainPanel(BufferedImage img) {
super();
this.img = img;
add(new JButton(pauseAction));
}
// draw the "game" background image within the JPanel if not null
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
// size this JPanel to match the image's size
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || img == null) {
return super.getPreferredSize();
}
int width = img.getWidth();
int height = img.getHeight();
return new Dimension(width, height);
}
}
// Action / ActionListener for JButton -- shows JDialog and darkens glasspane
#SuppressWarnings("serial")
class PauseAction extends AbstractAction {
private static final int ALPHA = 175; // how much see-thru. 0 to 255
private static final Color GP_BG = new Color(0, 0, 0, ALPHA);
private DeDialogPanel deDialogPanel = new DeDialogPanel(); // jpanel shown in JDialog
public PauseAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
// comp is our JButton
Component comp = (Component) e.getSource();
if (comp == null) {
return;
}
// create our glass pane
JPanel glassPane = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
// magic to make it dark without side-effects
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
// more magic below
glassPane.setOpaque(false);
glassPane.setBackground(GP_BG);
// get the rootpane container, here the JFrame, that holds the JButton
RootPaneContainer win = (RootPaneContainer) SwingUtilities.getWindowAncestor(comp);
win.setGlassPane(glassPane); // set the glass pane
glassPane.setVisible(true); // and show the glass pane
// create a *modal* JDialog
JDialog dialog = new JDialog((Window)win, "", ModalityType.APPLICATION_MODAL);
dialog.getContentPane().add(deDialogPanel); // add its JPanel to it
dialog.setUndecorated(true); // give it no borders (if desired)
dialog.pack(); // size it
dialog.setLocationRelativeTo((Window) win); // ** Center it over the JFrame **
dialog.setVisible(true); // display it, pausing the GUI below it
// at this point the dialog is no longer visible, so get rid of glass pane
glassPane.setVisible(false);
}
}
// JPanel shown in the modal JDialog above
#SuppressWarnings("serial")
class DeDialogPanel extends JPanel {
private static final Color BG = new Color(123, 63, 0);
public DeDialogPanel() {
JLabel pausedLabel = new JLabel("PAUSED");
pausedLabel.setForeground(Color.ORANGE);
JPanel pausedPanel = new JPanel();
pausedPanel.setOpaque(false);
pausedPanel.add(pausedLabel);
setBackground(BG);
int eb = 15;
setBorder(BorderFactory.createEmptyBorder(eb, eb, eb, eb));
setLayout(new GridLayout(0, 1, 10, 10));
add(pausedPanel);
add(new JButton(new FooAction("RESUME")));
add(new JButton(new FooAction("RESTART")));
add(new JButton(new FooAction("EXIT TO MAP")));
}
// simple action -- all it does is to make the dialog no longer visible
private class FooAction extends AbstractAction {
public FooAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
Component comp = (Component) e.getSource();
Window win = SwingUtilities.getWindowAncestor(comp);
win.dispose(); // here -- dispose of the JDialog
}
}
}
The GUI looks like this initially:
but then when the dialog shows and the glass pane is darkened, it looks like this:
So after about a month of working on my game I was drawn to this post once again. I implemented part of my game with what DontKnowMuchButGettingBetter's way and also implemented this by just adding the components to the GlassPane so to speak (Made a JPanel, set it to be GlassPane, did whatever on that Panel)...
The later implementation (GlassPane), isn't the best way to go about this because then you can't use the glass pane for other useful things.
I came back to my original idea to use a JLayeredPane. Having different Components on different levels and working off that. My issue before was that when components were getting repainted, the components in the backer layers were over painting the ones in the front layer.
Well I just came across a method called isOptimizedDrawingEnabled()... By making this method always return false for the JLayeredPane I was able to achieve what I wanted.

Update JPopupMenu height while visible

I have a popup menu in my application that I want to replace with a customized one so that it matches the look & feel of the rest of the application. Essentially, instead of having the normal menu items in the popup, I want reuse a component that already exist elsewhere in the application that lets you navigate through a hierarchy of items in a "paging" way instead of with sub-menus. So if you click on an item in the list that contains children then the next page will be displayed replacing the current items in the list with a list of the children of the clicked item.
The advantage of using the "paging" component is that it will fit in well with the rest of the application (it is already used in other places that are not popups) and it has some nice looking animation effects when navigating between pages.
The problem I'm having is that the preferred height of the paging component changes when showing different pages (the amount of items in the list change) and I want the popup menu height to update so that it fits the paging component exactly, but so far my attempts to update the height of the popup menu while it is visible have failed.
Below is an example application that demonstrates the problem:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
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.JPopupMenu;
public class PopupSizeTestFrame extends JFrame {
private static final int PREFFERED_WIDTH = 300;
private static JPanel resizingPanel;
private static JPopupMenu popupMenu;
private static PopupSizeTestFrame frame;
private static void resizePopupMenu() {
// What should I do here so that the size of the popup menu is updated?
/**
* Calling pack() works in this example, but I cannot call pack in the
* actual application since there is a smooth transition animation when
* clicking on the inner panel and pack() essentially re-adds the
* components of the popup menu (removeNotify and addNotify is called),
* which interferes with the animation and causes the menu to flicker.
* The flickering when clicking the inner panel can also be seen in this
* example when uncommenting the pack() call.
*/
//popupMenu.pack();
//
// I tried combinations of the following, without success:
//popupMenu.invalidate();
//popupMenu.revalidate();
//popupMenu.validate();
//popupMenu.doLayout();
// Repaint
popupMenu.repaint();
}
public static void main(String args[]) {
// Create popup child panel with height that changes when clicked
resizingPanel = new JPanel(new BorderLayout());
int initialHeight = 30;
final JLabel label = new JLabel("Click me (" + initialHeight + "px)");
resizingPanel.add(label);
resizingPanel.setBackground(Color.GREEN);
resizingPanel.setPreferredSize(new Dimension(PREFFERED_WIDTH, initialHeight));
resizingPanel.addMouseListener(new MouseAdapter() {
private int clickCount = 0;
#Override
public void mouseClicked(MouseEvent e) {
int height = ((clickCount % 3) + 1) * 50;
resizingPanel.setPreferredSize(new Dimension(PREFFERED_WIDTH, height));
clickCount++;
label.setText("Click me (" + height + "px)");
resizePopupMenu();
}
});
// Create popup
popupMenu = new JPopupMenu();
popupMenu.setLayout(new BorderLayout());
popupMenu.add(new JLabel("Header"), BorderLayout.NORTH);
popupMenu.add(resizingPanel, BorderLayout.CENTER);
popupMenu.add(new JLabel("Footer"), BorderLayout.SOUTH);
// Create frame
frame = new PopupSizeTestFrame();
frame.setLayout(new BorderLayout());
frame.setPreferredSize(new Dimension(400, 400));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
popupMenu.show(frame, e.getX(), e.getY());
}
}
});
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
frame.setVisible(true);
}
});
}
}
When running the example above you will see that the popup menu size is updated if it is closed and opened after the inner panel was clicked, but it is not updated while the popup is visible.
What can I do in resizePopupMenu() to update the height of the JPopupMenu?
For the test app in the question the popup was always a heavyweight component and the following worked (as suggested by mKorbel)
private static void resizePopupMenu() {
SwingUtilities.getWindowAncestor(popupMenu).pack();
}
For the actual application when the popup was inside the bounds the application it was created as a lightweight component which prevented it from being resized with pack() and also prevented it from resizing past the application bounds.
I tried setting this property...
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
but then a mediumweight component was created and it would still not resize past the application bounds.
So I had to first force all popups of the "owner" component to be heavyweight with the following piece of unfortunate code
// Set owner to component on which popup is shown or any of its parents
final Component owner = ...;
AccessController.doPrivileged(new PrivilegedAction<Void>() {
#Override
public Void run() {
try {
Field field;
if (System.getProperty("java.version").startsWith("1.6.0")) {
Class clazz = Class.forName("javax.swing.PopupFactory");
field = clazz.getDeclaredField("forceHeavyWeightPopupKey");
} else { //JDK 1.7.0, 1.8.0
Class clazz = Class.forName("javax.swing.ClientPropertyKey");
field = clazz.getDeclaredField("PopupFactory_FORCE_HEAVYWEIGHT_POPUP");
}
field.setAccessible(true);
owner.putClientProperty(field.get(null), Boolean.TRUE);
} catch (Exception ex) {
Exceptions.printStackTrace(ex);
}
return null;
}
});
After forcing the popup menu to always be a heavyweight component this
SwingUtilities.getWindowAncestor(popupMenu).pack();
also worked to update the size of the popup, even beyond the bounds of the application.
I think you can add a PopupMenuListener to the popup menu and handle the menuWillBecomeVisible(...) event to set the size of the popup.

How to make buttons display and work in my java applet

I Have applet with a image of a java cup that can be repositioned by the clicking of 5 buttons to move it in the main area of the applet window.
the issue im having is the buttons are not being displayed in im applet the only thing that is showing is my cup.gif on the blue background, can any one see the problem with the code ,i want the buttons to show and work
And yes guys I know AWT is old but i have to learn it for my course...any help would be great thanks guys!
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class moveIt extends Applet implements ActionListener
{
private Image cup;
private Panel Keypad = new Panel();
public int top = 15;
public int left = 15;
private Button Keyarray[] = new Button[5];
public void init ()
{
cup=getImage(getDocumentBase(), "cup.gif");
Canvas myCanvas= new Canvas();
Keyarray[0] = new Button ("Up");
Keyarray[1] = new Button ("Left");
Keyarray[2] = new Button ("Down");
Keyarray[3] = new Button ("Right");
Keyarray[4] = new Button ("Center");
setBackground(Color.BLUE);
Panel frame = new Panel();
frame.setLayout(new BorderLayout());
frame.add(myCanvas, BorderLayout.NORTH);
frame.add(Keypad, BorderLayout.SOUTH);
Keypad.setLayout(new BorderLayout());
Keypad.add(Keyarray[0], BorderLayout.NORTH);
Keypad.add(Keyarray[1], BorderLayout.WEST);
Keypad.add(Keyarray[2], BorderLayout.SOUTH);
Keypad.add(Keyarray[3], BorderLayout.EAST);
Keypad.add(Keyarray[4], BorderLayout.CENTER);
Keyarray[0].addActionListener(this);
Keyarray[1].addActionListener(this);
Keyarray[2].addActionListener(this);
Keyarray[3].addActionListener(this);
Keyarray[4].addActionListener(this);
}//end of method init
public void paint(Graphics g)
{
g.drawImage(cup, left, top, this);
}
public void actionPerformed(ActionEvent e)
{
String arg= e.getActionCommand();
if (arg.equals("Up"))
top -= 15;
if (arg.equals("down"))
top += 15;
if (arg.equals("Left"))
left -= 15;
if (arg.equals("Right"))
left += 15;
if (arg.equals("Center"))
{
top=60;
} left=125;
repaint();
}//end paint method
}//end of class
You never add the frame to the applet this.add(frame)
Once you do, you will have to setOpaque(false) to the frame so you can see the background
Important Side Notes:
Instead of painting on the Applet directly, you should be painting rather on a JPanel and override it's paintComponent method.
You Need to call super.paint(g) or super.paintComponent(g)(for JPanel) in the paint method, as to not break the paint chain and see all kinds of wierd paint artifacts
I just noticed the AWT components. AWT is pretty much obsolete. You should move it up to using Swing. See the Swing Tutorials
Use Java naming convention. Variables begin with lower case letters, using camelCasing e.g. Keyarray → keyArray. Class names begin with capital letters using CamelCasing e.g. moveIt → MoveIt

How do I change button labels in a grid?

I'm trying to make a game which involves moving pieces by dragging and dropping them from square to square. However, I'm trying to do so using buttons with labels (as an exercise). So, for instance, a button with the label "W" should change its label to "" (blank) when I press the mouse on it and release on a second valid button (one with another blank label). Then that second button should change its label from "" (blank) to "W".
Using graphics in Java is entirely new to me. Suffice it to say, I'm not sure how to accomplish the aforementioned task. Here's my code so far:
import javax.swing.*;
import javax.swing.JButton;
import java.awt.GridLayout;
import java.awt.event.*;
class Boardgame extends JFrame implements MouseListener {
JFrame frame = new JFrame("Boardgame");
JButton[][] bogrid;
public Boardgame ()
{
frame.setLayout(new GridLayout(8,8));
bogrid = new JButton[8][8];
for (int i=0;i<8;i++)
{
for (int j=0;j<2;j++)
{
bogrid[j][i] = new JButton("B");
frame.add(bogrid[j][i]);
}
for (int j=2;j<6;j++)
{
bogrid[j][i] = new JButton();
frame.add(bogrid[j][i]);
}
for (int j=6;j<8;j++)
{
bogrid[j][i] = new JButton("W");
frame.add(bogrid[j][i]);
}
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setSize(405, 450);
frame.setVisible(true);
}
public void mouseClicked(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
public void mousePressed(MouseEvent e)
{
}
class MyAction implements ActionListener {
Boardgame bo;
MyAction(Boardgame b)
{
bo = b;
}
}
}
First off, you'll need to use a MouseListener to listen for mousePressed and mouseReleased actions. This means that you most definitely should not be using JButtons for this type of program but rather either JLabels, or a logical grid of images, since JButtons should respond to ActionListeners, not MouseListeners (with rare exceptions). I suggest using JLabels, since it will be easy for them to hold and set text and to give you the text they hold.
Next, you would add your MouseListener to your JLabels, and on mousePressed, get the text held by the pressed JLabel. The MouseEvent parameter's getSource() method will return to you the pressed (and released) JLabel.
So inside of your for loops, you will need to add something like:
bogrid[j][i] = new JLabel("B");
bogrid[j][i].addMouseListener(myMouseListener);
frame.add(bogrid[j][i]);
Where myMouseListener is your MouseListener object.
Edit
You ask in comment:
Initial question: using JLabel instead of JButton yields a window that appears to be a large empty field with a bunch of floating labels. How do I make it appear as a grid with lines demarcating the individual spaces?
Consider giving your JLabel a border, and consider giving the GridLayout some horizontal and vertical gaps.
For the layout use the GridLayout constructor that takes 4 int parameters, not 2, with the 3rd and 4th parameters being for the horizontal and vertical gaps:
int gap = 4; // or whatever number looks nice
frame.setLayout(new GridLayout(8, 8, gap, gap));
For the border, consider using a LineBorder that is added to the JLabel in the loop where you create it. If that Border crowds your text too much, you could use a CompoundBorder where the inner border is an EmptyBorder with suitable constants and the outer border is a LineBorder.

Categories