so I have 4 JLists to contain 4 different parts of a skateboard, the trucks, the wheels, miscellaneous, and decks.
I have four enums set up in my class SkateBoardParts, as such:
public class SkateBoardParts {
public enum Decks {
FIRST_DECK(10),
....
}
double cost;
private Decks(double c){
cost = c;
}
... getCost blah
}
In my GUI, I have a button to calculate. I have an action listener on that button. My goal is to get the cost of all the selected values in the JLists and add them together to get a total. I have the JLists set up as fields. How do I do this? Would I get the index and then use that index to select the value in the enum? Something like this? (I get an error on truckIndex)
double total = 0;
int truckIndex = trucksList.getSelectedIndex();
total += SkateBoardParts.Trucks.truckIndex.getCost();
if you want my entire code for my GUI thus far:
https://pastebin.com/CiSsV8qR
my enum:
https://pastebin.com/WqXs05aK
A simple solution is to store the value of each component at the point at which the user selects the part:
private double partCost = 0.0;
...
JList<SkateBoardPart> list = new JList(SkateBoardPart.values());
list.addListSelectionListener(ev -> partCost = list.getSelectedValue().getCost());
That will keep the cost up to date each time the user selects a part.
Define your JList as follows
private final JList<SkateBoardParts> trucksList = new JList(trucksArray);
In your action listener do the following
JList<SkateBoardParts> list = (JList<SkateBoardParts>) e.getSource();
SkateBoardParts obj = (SkateBoardParts) list.getSelectedValue();
obj.getCost();
Update
Here is an example of SSCCE. Please try to post something similar for better help sooner.
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.SwingUtilities;
public class JListExample extends JFrame {
private final JList<Trucks> trucksList;
public JListExample() {
//create the model and add elements
DefaultListModel<Trucks> listModel = new DefaultListModel<>();
for (Trucks truk: Trucks.values()) {
listModel.addElement(truk);
}
//create the list
trucksList = new JList<>(listModel);
trucksList.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent me) {
JList<Trucks> list = (JList<Trucks>) me.getSource();
Trucks truck = (Trucks) list.getSelectedValue();
System.out.println("Cost " + truck.getCost());
}
});
add(trucksList);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("JList Example");
this.setSize(200, 200);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new JListExample();
}
});
}
}
enum Trucks {
SEVEN_INCH_AXLE(35),
EIGHT_INCH_AXLE(40),
EIGHT_AND_HALF_INCH_AXLE(45);
double cost;
private Trucks(double c) {
cost = c;
}
public double getCost() {
return cost;
}
}
Related
I'm creating an speed reader so I'm using a swingx.Timer object to display the words at a given time.I set the time to 1sec for testing. I had the code working before but then after closing eclipse and coming back to it the code doesn't work anymore. The timer does not call the actionlistener thus not performing the action it is supposed to perform. Here is my code. I read other questions talking about timer being a daemon thread and ending with main. However I don't think this is the case in my code but I could be wrong. Can someone help me point out my error?
package reader;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JTextPane;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JMenu;
import java.awt.event.*;
import java.io.IOException;
import java.sql.Time;
import javax.swing.Timer;
public class ReaderPad extends JPanel{
public JButton startBtn, stopBtn, resetBtn;
public JList speedMenu;
public JMenuBar topMenu;
public JTextPane textPad;
public JScrollPane scroll;
public Timer timer;//to control the speed of the reader
public int speed; //the speed set for the reader, i.e. 100 words per minute
public JLabel speedLabel;
public JTextField speedText;
int wordLength; //size of text
String[] lines; //a line of text composed of 10 words from the text entered
int wpm;
int i;//index of word set being used
public ReaderPad(){
this.setLayout(new BorderLayout());
i = 0;
speedLabel = new JLabel("words per minute");
speedText = new JTextField();
speedText.setColumns(3);
startBtn = new JButton("Start");
stopBtn = new JButton("Stop");
resetBtn = new JButton("Reset");
textPad = new JTextPane();
topMenu = new JMenuBar();
textPad.setEditable(true);
textPad.setFont(new Font("Serif", Font.PLAIN,25));
textPad.setText("welcome to speed reader. Use CTRL + c to paste your text\n"
+ "Press start to begin");
scroll = new JScrollPane(textPad);
//create top menu bar
topMenu.add(startBtn);
topMenu.add(stopBtn);
topMenu.add(resetBtn);
topMenu.add(speedLabel);
topMenu.add(speedText);
//topMenu.add(speedMenu);
this.add(topMenu, BorderLayout.NORTH);
this.add(scroll, BorderLayout.CENTER);
//set listeners for buttons
Actions listener = new Actions();
startBtn.addActionListener(listener);
stopBtn.addActionListener(listener);
resetBtn.addActionListener(listener);
}//end of constructor
public void setFontSize(String size){
Font font = textPad.getFont();
String s = font.getName();
textPad.setFont(new Font(s, Font.PLAIN, Integer.valueOf(size)));
}
public void setFontColor(String color){
}
//sets background color
public void setBackgroud(String color){
}
public void setSpeed(String speed){
//speed = speed.replace("X", "");//remove the times symbol
if(speed.isEmpty())//set default
this.speed = 100;
else
this.speed = Integer.valueOf(speed);
}
public int getSpeed(){
return this.speed;
}
public void startReader(){//words per minute
int speed = getSpeed();//wpm selected by the user
System.out.println("speed: " + speed);
String text = textPad.getText();
// System.out.println(text);
lines = text.split(" ");
wordLength = lines.length;//get the number of words in the text
System.out.println("length: "+ wordLength);
//System.out.println(wordLength.length);
if(text.isEmpty()){
textPad.setText("You didn't enter any text in the text area.\n"
+"Please enter some text to begin.");
}
else{//set timer
//calculate speed first: time = (speed chosen * number of workds in text) = (sec/words)*wordsize
//wpm = (1/speed)*wordLength*60*1000; //multiply by 60 secons
wpm = 1000;
System.out.println("wpm: "+ wpm);
TimerReader counter = new TimerReader();
timer = new Timer(1000, counter);
timer.start();
System.out.println(timer.isRunning());
}
}
public void stopReader(){
}
//listener class
public class Actions implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
String source = e.getActionCommand();//read the button asking for the request
if(source.equals("Reset")){
textPad.setText("");
if(timer.isRunning())
timer.stop();
}
else if(source.equals("Start")){
//first read the speed selected and set the speed
setSpeed(speedText.getText());
startReader();
}
else if (source.equals("Stop"))
i = 0;
timer.stop();
}
}
public class TimerReader implements ActionListener{
#Override
public void actionPerformed(ActionEvent e){
//once the timer is called the textpad starts displaying the words
String s = lines[i];
i++;
textPad.setText(s);
System.out.println(i);
System.out.println(e.getActionCommand());
System.out.print(textPad.getText());
}
}//end of inner class
}//end of ReaderPad class
Remove timer.stop() from the end of Actions actionPerformed method...
public class Actions implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
String source = e.getActionCommand();//read the button asking for the request
if (source.equals("Reset")) {
textPad.setText("");
if (timer.isRunning()) {
timer.stop();
}
} else if (source.equals("Start")) {
//first read the speed selected and set the speed
setSpeed(speedText.getText());
startReader();
} else if (source.equals("Stop")) {
i = 0;
}
// This is stopping the timer AFTER it was already started
//timer.stop();
}
}
I'm trying to move a JButton to the location of another one but the button I want to move moves to a wrong point. My idea is that this happens because I use multiple JPanels. I tried: getLocationOnScreen, getBounds and getLocation, but none of them worked, how to solve it? When an user selects a card on the table or from a player by clicking this card the the target is set, the sender is set by clicking a card from the top panel. playerCardSpotTargetand playerCardSpotSender are both of type Card. When I try to move the for example eight of diamonds this card moves to a point behind the eight and nine of clubs.
Code:
This events belong to the blue cards on the table and the cards for the players(I have to change the name of the event, I know).
private void PlayerOneMouseClicked(java.awt.event.MouseEvent evt){
playerCardSpotTarget=(Card)evt.getSource();
if(playerCardSpotTarget.isBorderPainted()){
playerCardSpotTarget.setBorderPainted(false);
}
else{
playerCardSpotTarget.setBorderPainted(true);
}
}
This event belongs to the cards in the top panel.
private void MouseClicked(java.awt.event.MouseEvent evt) {
playerCardSpotSender=(Card)evt.getSource();
System.out.println(playerCardSpotSender.suit+" "+playerCardSpotSender.kind);
if (playerCardSpotTarget != null && playerCardSpotTarget.isBorderPainted()) {
playerCardSpotSender.setLocation(playerCardSpotTarget.getLocation());
System.out.println(playerCardSpotTarget.getLocationOnScreen());
System.out.println(playerCardSpotSender.getLocationOnScreen());
}
}
Layout for the center panel in the JFrame (BorderLayout.CENTER)
JPanel centerPanelNorth;
JPanel centerPanelCenter;
JPanel centerPanelEast;
JPanel centerPanelSouth;
JPanel centerPanelWest;
JLabel tablePicture;
JPanel centerPanel;
centerPanel=new JPanel(new BorderLayout());
tablePicture = new JLabel(new ImageIcon(this.getClass().getResource(Constants.POKERTABLE_ICON)));
centerPanelNorth=new JPanel();
centerPanelEast=new JPanel();
centerPanelSouth=new JPanel();
centerPanelWest=new JPanel();
centerPanelCenter=new JPanel();
centerPanel.add(centerPanelCenter,BorderLayout.CENTER);
centerPanelCenter.add(tablePicture);
//add
tablePicture.add(boardCard1);
tablePicture.add(boardCard2);
tablePicture.add(boardCard3);
tablePicture.setLayout(new GridBagLayout());
//PLAYER NORTH
centerPanel.add(centerPanelNorth,BorderLayout.NORTH);
centerPanelNorth.add(playerOneCardOne);
centerPanelNorth.add(playerOneCardTwo);
//PLAYER EAST
centerPanel.add(centerPanelEast,BorderLayout.EAST);
centerPanelEast.setLayout(new BoxLayout(centerPanelEast,BoxLayout.X_AXIS));
centerPanelEast.add(playerTwoCardOne);
centerPanelEast.add(playerTwoCardTwo);
//PLAYER SOUTH
centerPanel.add(centerPanelSouth,BorderLayout.SOUTH);
centerPanelSouth.add(playerThreeCardOne);
centerPanelSouth.add(playerThreeCardTwo);
//PLAYER WEST
centerPanel.add(centerPanelWest,BorderLayout.WEST);
centerPanelWest.setLayout(new BoxLayout(centerPanelWest,BoxLayout.X_AXIS));
centerPanelWest.add(playerFourCardOne);
centerPanelWest.add(playerFourCardTwo);
Card.java
public class Card extends JButton{
int suit;
int kind;
boolean known;
String iconPath;
Integer boardPosition;
}
Animating the button movement isn't actually the hardest problem, the hardest problem is trying to move the data about in away in which you can manage it and how to connect the source component with the target...
To start with, you need a means by which you can move a component across container boundaries. While there are probably a few ways to do this, the simplest is to probably use the glass pane of the frame
public class AnimationPane extends JPanel {
public AnimationPane() {
setOpaque(false);
setLayout(null);
}
}
This is nothing special, it's just a JPanel which is transparent and has no layout manager, normally, not recommended, but in the case, we're going to take control..
Now, we need some way to animate the movement...
public enum Animator {
INSTANCE;
private List<IAnimatable> animatables;
private Timer timer;
private Animator() {
animatables = new ArrayList<>(25);
timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
IAnimatable[] anins = animatables.toArray(new IAnimatable[animatables.size()]);
for (IAnimatable animatable : anins) {
animatable.update();
}
}
});
timer.start();
}
public void addAnimatable(IAnimatable animatable) {
animatables.add(animatable);
}
public void removeAnimatable(IAnimatable animatable) {
animatables.remove(animatable);
}
}
public interface IAnimatable {
public void update();
}
public interface IMoveAnimatable extends IAnimatable{
public JComponent getSourceComponent();
public IImportable getImportable();
}
So the Animator is the core "engine", it's basically a Swing Timer which simply calls update on any IAnimatables it might be managing. The intention with this approach is you can have a number of animations running, but it won't degrade the system (greatly) as you only have a single update/timer point.
Now, normally I'd just use something like the Timing Framework or the Trident Framework or even the Universal Tween Engine
The IAnimatable interfaces just define the basic contracts that provide functionality for the animation.
We need to define some kind of contract the defines objects which can take part in the animation process and receive information, or the "target"
public interface IImportable {
public JComponent getView();
public void importValue(String value);
}
public abstract class AbstractImportable extends JPanel implements IImportable {
#Override
public JComponent getView() {
return this;
}
}
Now it occurs to me that we could tap into the pre-existing Transferable API, which would allow you to also implement drag-n-drop (and even copy/cut and paste), this would be used to define a lookup mechanism where you match a given data type with potential targets based on the DataFlavor ... but I'll leave you to investigate how that might work...
The core mechanism basically removes the source component from it's current container, adds it to the AnimationPane, moves the source component across the AnimationPane and then imports the data into the target...
The problem is, you need to translate the location of component from it's current context to the AnimationPane.
A components location is relative to it's parents context. It's relatively easy to do with SwingUtilities.convertPoint(Component, Point, Component)
We calculate the origin point of the source component and the target point, relative to the AnimationPane. We then, on each call to update, calculate the progress of the animation. Instead of using a "delta" movement, we calculate the different between the time we started and a predefined duration (1 second in this case), this generally produces a more flexible animation
public class DefaultAnimatable implements IMoveAnimatable {
public static final double PLAY_TIME = 1000d;
private Long startTime;
private JComponent sourceComponent;
private IImportable importable;
private JComponent animationSurface;
private Point originPoint, destinationPoint;
private String value;
public DefaultAnimatable(JComponent animationSurface, JComponent sourceComponent, IImportable importable, String value) {
this.sourceComponent = sourceComponent;
this.importable = importable;
this.animationSurface = animationSurface;
this.value = value;
}
public String getValue() {
return value;
}
public JComponent getAnimationSurface() {
return animationSurface;
}
#Override
public JComponent getSourceComponent() {
return sourceComponent;
}
#Override
public IImportable getImportable() {
return importable;
}
#Override
public void update() {
if (startTime == null) {
System.out.println("Start");
IImportable importable = getImportable();
JComponent target = importable.getView();
originPoint = SwingUtilities.convertPoint(getSourceComponent().getParent(), getSourceComponent().getLocation(), getAnimationSurface());
destinationPoint = SwingUtilities.convertPoint(target.getParent(), target.getLocation(), getAnimationSurface());
destinationPoint.x = destinationPoint.x + ((target.getWidth() - getSourceComponent().getWidth()) / 2);
destinationPoint.y = destinationPoint.y + ((target.getHeight() - getSourceComponent().getHeight()) / 2);
Container parent = getSourceComponent().getParent();
getAnimationSurface().add(getSourceComponent());
getSourceComponent().setLocation(originPoint);
parent.invalidate();
parent.validate();
parent.repaint();
startTime = System.currentTimeMillis();
}
long duration = System.currentTimeMillis() - startTime;
double progress = Math.min(duration / PLAY_TIME, 1d);
Point location = new Point();
location.x = progress(originPoint.x, destinationPoint.x, progress);
location.y = progress(originPoint.y, destinationPoint.y, progress);
getSourceComponent().setLocation(location);
getAnimationSurface().repaint();
if (progress == 1d) {
getAnimationSurface().remove(getSourceComponent());
Animator.INSTANCE.removeAnimatable(this);
animationCompleted();
}
}
public int progress(int startValue, int endValue, double fraction) {
int value = 0;
int distance = endValue - startValue;
value = (int) Math.round((double) distance * fraction);
value += startValue;
return value;
}
protected void animationCompleted() {
getImportable().importValue(getValue());
}
}
Okay, now this produces a linear animation, which is pretty boring, now if you have plenty of time, you could create an easement like this or just use one of the animation frameworks...
Now, we need to put it together...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class AnimationTest {
public static void main(String[] args) {
new AnimationTest();
}
public AnimationTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
AnimationPane animationPane = new AnimationPane();
LeftPane leftPane = new LeftPane(animationPane);
RightPane rightPane = new RightPane();
leftPane.setImportabale(rightPane);
rightPane.setImportabale(leftPane);
JFrame frame = new JFrame("Testing");
frame.setLayout(new GridLayout(1, 2));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(leftPane, BorderLayout.WEST);
frame.add(rightPane, BorderLayout.WEST);
frame.setGlassPane(animationPane);
animationPane.setVisible(true);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class RightPane extends AbstractImportable {
private IImportable source;
private JButton imported;
private String importedValue;
public RightPane() {
setLayout(new GridBagLayout());
setBorder(new LineBorder(Color.DARK_GRAY));
}
public void setImportabale(IImportable source) {
this.source = source;
}
#Override
public void importValue(String value) {
if (imported != null) {
// May re-animate the movement back...
remove(imported);
}
importedValue = value;
imported = new JButton(">> " + value + "<<");
add(imported);
revalidate();
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class LeftPane extends AbstractImportable {
private IImportable importable;
public LeftPane(AnimationPane animationPane) {
setLayout(new GridBagLayout());
JButton btn = new JButton("Lefty");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
DefaultAnimatable animatable = new DefaultAnimatable(animationPane, btn, importable, "Lefty");
Animator.INSTANCE.addAnimatable(animatable);
}
});
add(btn);
setBorder(new LineBorder(Color.DARK_GRAY));
}
public void setImportabale(IImportable target) {
this.importable = target;
}
#Override
public void importValue(String value) {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Maybe use mousePressed(),when you move the card,you press it until the target.And in the process, you get the information about JButton.getLocation() by the event,and than you need to solve the collision problem between two cards.So it's good!Of course, this is my advice ,you should have better idea!
I'm using GXT 3 Grid with InlineEdit mode following (more or less) the example code on their site. I don't think there is a way to get the check box cell to fire the 'EditComplete' event and if so, I'm not sure how I would, upon receiving it, disable the date cell on that same row. Just look for the comment: "// not firing for checkbox:" in the code below.
The following code works in an Eclipse web application project - you just need to use it in your 'onModuleLoad' method as demonstrated here:
public void onModuleLoad() {
GridInlineEditingTest j = new GridInlineEditingTest();
}
Here's the code:
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.google.gwt.cell.client.DateCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor.Path;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.cell.core.client.form.CheckBoxCell;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.data.shared.ModelKeyProvider;
import com.sencha.gxt.data.shared.PropertyAccess;
import com.sencha.gxt.data.shared.Store;
import com.sencha.gxt.widget.core.client.FramedPanel;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.container.BoxLayoutContainer.BoxLayoutPack;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData;
import com.sencha.gxt.widget.core.client.container.Viewport;
import com.sencha.gxt.widget.core.client.event.CompleteEditEvent;
import com.sencha.gxt.widget.core.client.event.CompleteEditEvent.CompleteEditHandler;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.event.SelectEvent.SelectHandler;
import com.sencha.gxt.widget.core.client.form.CheckBox;
import com.sencha.gxt.widget.core.client.form.DateField;
import com.sencha.gxt.widget.core.client.form.DateTimePropertyEditor;
import com.sencha.gxt.widget.core.client.grid.ColumnConfig;
import com.sencha.gxt.widget.core.client.grid.ColumnModel;
import com.sencha.gxt.widget.core.client.grid.Grid;
import com.sencha.gxt.widget.core.client.grid.Grid.GridCell;
import com.sencha.gxt.widget.core.client.grid.GridView;
import com.sencha.gxt.widget.core.client.grid.editing.GridEditing;
import com.sencha.gxt.widget.core.client.grid.editing.GridInlineEditing;
public class GridInlineEditingTest {
public GridInlineEditingTest() {
VerticalLayoutContainer vlc = new VerticalLayoutContainer();
vlc.add(createGrid(), new VerticalLayoutData(1, 1));
Viewport vp = new Viewport();
vp.add(vlc);
RootPanel.get().add(vp);
}
interface PlaceProperties extends PropertyAccess<Plant> {
ValueProvider<Plant, Date> available();
#Path("id")
ModelKeyProvider<Plant> key();
ValueProvider<Plant, String> name();
ValueProvider<Plant, Boolean> indoor();
}
private static final PlaceProperties properties = GWT.create(PlaceProperties.class);
protected Grid<Plant> grid;
private FramedPanel panel;
private ListStore<Plant> store;
private DateField dateField;
public Widget createGrid() {
if (panel == null) {
ColumnConfig<Plant, String> nameCol = new ColumnConfig<Plant, String>( properties.name(), 220, "Name" );
ColumnConfig<Plant, Date> dateCol = new ColumnConfig<Plant, Date>( properties.available(), 95, "Date" );
ColumnConfig<Plant, Boolean> indorCol = new ColumnConfig<Plant, Boolean>( properties.indoor(), 55, "Indoor");
// display formatting
DateCell dateCell = new DateCell(DateTimeFormat.getFormat(PredefinedFormat.DATE_SHORT));
dateCol.setCell(dateCell);
// display a checkbox in the gridview
indorCol.setCell(new CheckBoxCell());
List<ColumnConfig<Plant, ?>> l = new ArrayList<ColumnConfig<Plant, ?>>();
l.add(nameCol);
l.add(dateCol);
l.add(indorCol);
ColumnModel<Plant> columns = new ColumnModel<Plant>(l);
store = new ListStore<Plant>(properties.key());
store.setAutoCommit(false);
store.addAll(getPlants());
GridView<Plant> gridView = new GridView<Plant>();
grid = new Grid<Plant>(store, columns, gridView);
grid.getView().setAutoExpandColumn(nameCol);
// EDITING//
final GridEditing<Plant> editing = new GridInlineEditing<Plant>(grid);
dateField = new DateField(new DateTimePropertyEditor(DateTimeFormat.getFormat(PredefinedFormat.DATE_SHORT)));
dateField.setClearValueOnParseError(false);
editing.addEditor(dateCol, dateField);
CheckBox checkField = new CheckBox();
editing.addEditor(indorCol, checkField);
editing.addCompleteEditHandler( new CompleteEditHandler<Plant>(){
// not firing for checkbox:
#Override
public void onCompleteEdit(CompleteEditEvent<Plant> event) {
GridCell cell = event.getEditCell();
int row = cell.getRow();
int col = cell.getCol();
System.out.println("got here. row "+row+", col "+col);
}
});
panel = new FramedPanel();
panel.setHeadingText("Editable Grid Example");
panel.setPixelSize(600, 400);
panel.addStyleName("margin-10");
VerticalLayoutContainer con = new VerticalLayoutContainer();
con.setBorders(true);
con.add(grid, new VerticalLayoutData(1, 1));
panel.setWidget(con);
panel.setButtonAlign(BoxLayoutPack.CENTER);
panel.addButton(new TextButton("Reset", new SelectHandler() {
#Override
public void onSelect(SelectEvent event) {
store.rejectChanges();
}
}));
panel.addButton(new TextButton("Save", new SelectHandler() {
#Override
public void onSelect(SelectEvent event) {
store.commitChanges();
}
}));
}
return panel;
}
private static int AUTO_ID = 0;
public class Plant {
private DateTimeFormat df = DateTimeFormat.getFormat("MM/dd/y");
private int id;
private String name;
private String light;
private double price;
private Date available;
private boolean indoor;
private String color;
private int difficulty;
private double progress;
public Plant() {
id = AUTO_ID++;
difficulty = (int) (Math.random() * 100);
progress = Math.random();
}
public Plant(String name, String light, double price, String available, boolean indoor) {
this();
setName(name);
setLight(light);
setPrice(price);
setAvailable(df.parse(available));
setIndoor(indoor);
}
public int getId() { return id; }
public double getProgress() { return progress; }
public String getColor() { return color; }
public int getDifficulty() { return difficulty; }
public Date getAvailable() { return available; }
public String getLight() { return light; }
public String getName() { return name; }
public double getPrice() { return price; }
public boolean isIndoor() { return indoor; }
public void setId(int id) { this.id = id; }
public void setProgress(double progress) { this.progress = progress; }
public void setAvailable(Date available) { this.available = available; }
public void setDifficulty(int difficulty) { this.difficulty = difficulty; }
public void setColor(String color) { this.color = color; }
public void setIndoor(boolean indoor) { this.indoor = indoor; }
public void setLight(String light) { this.light = light; }
public void setName(String name) { this.name = name; }
public void setPrice(double price) { this.price = price; }
#Override
public String toString() {
return name != null ? name : super.toString();
}
}
public List<Plant> getPlants() {
List<Plant> plants = new ArrayList<Plant>();
plants.add(new Plant("Bloodroot", "Mostly Shady", 2.44, "03/15/2006", true));
plants.add(new Plant("Columbine", "Shade", 9.37, "03/15/2006", true));
plants.add(new Plant("Marsh Marigold", "Mostly Sunny", 6.81, "05/17/2006", false));
plants.add(new Plant("Cowslip", "Mostly Shady", 9.90, "03/06/2006", true));
plants.add(new Plant("Dutchman's-Breeches", "Mostly Shady", 6.44, "01/20/2006", true));
plants.add(new Plant("Ginger, Wild", "Mostly Shady", 9.03, "04/18/2006", true));
return plants;
}
}
thanks. and have a great day!!
You are setting a checkbox cell in the column, and then also attaching a field as an inline editor for the column. So if the user clicks the checkbox (cell), you are expecting that click to be ignored, but instead a checkbox (field) to show up over it, which the user may then click?
Instead what is happening is that the checkbox (cell) is reporting that it is using that click event to do something useful - it is changing its value. As a result, the grid editing mechanism ignores the click, so the checkbox (field) never goes into edit mode, and so of course it doesn't complete edit mode.
What are you trying to achieve by making it the purpose of two different checkboxes to be drawn in the same place, and function differently? If you are trying to use the CheckBoxCell instance as a way to always draw the checkbox symbol in the grid cell, there are two main choices:
Skip the CheckBox field in the inline editing, and just let the cell take care of it. It will not fire the editing events, but it will still directly interact with the store. You can listen to the cell's events if you need to, or just to the record change events from the store, or you can subclass the cell to modify behavior.
Removing the event handing guts of the CheckBoxCell to prevent it from handling the event - this may be as simple as overriding onBrowserEvent to do nothing, though I suspect that you actually will want to prevent its check changing behavior entirely so that the Inline Editing version takes care of it
Finally, remember that the purpose of inline editing is to keep the grid from being a mass of fields, and to make it only draw those fields when the user actually interacts with it. This means that the user must first click a field to get something like a checkbox to show up, then interface with the field to change it. Looking one more time at the CheckBox field in an inline editable grid (though this time with a custom cell) at http://www.sencha.com/examples/#ExamplePlace:inlineeditablegrid you'll see that this means two clicks to change a value and get the CompleteEditing event (as well as the various other field change events) that you are after - is this really what you have in mind?
As per the Source Code of CheckBoxCell#isEditing() that says:
A checkbox is never in "edit mode". There is no intermediate state between checked and unchecked.
Find the alternate solution here How to get the row index of selected checkbox on grid GXT.
Please have a look at GXT checkbox in grid
I'm making a game with multiple asteroids going down. The goal is to dodge as many asteroids for as long as you can. I made it so that as soon as an asteroid reaches the bottom of the screen it is send back up, now i want to count every time it gets to the bottom and add it to the score.
My problem is that all the asteroids are the same class so if I use:
if(y>700){
y=-50; //
x= (int) (Math.random()*670); // To send the asteroid back up
setLocation(x,y); //
score++; // To add up the score
System.out.println(score); // To print the score
Every asteroid adds op his own amount of times it has reached the bottom, but I want to know how many asteroids have reached the bottom in total. So I figured I have to get the score out of the asteroid class and add it up in an other class but I don't know how.
This is the code of the asteroid class:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Astroid extends JPanel implements ActionListener
{
public int yVelocity = 1;
public int x = (int) (Math.random()*650), y = (int) (Math.random()*-1000);
public Timer timer;
private int score;
public Astroid(int x,int y)
{
this.setLocation(x, y);
this.setSize(25, 25);
this.setBackground(Color.WHITE);
this.setVisible(true);
}
{
this.timer = null;
this.timer = new Timer(10,new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0)
{
setLocation(x,(y+=yVelocity));
timer.setDelay(10);
repaint();
if(y>700){
y=-50;
x= (int) (Math.random()*670);
setLocation(x,y);
score++;
System.out.println(score);
}
}
});
timer.start();
}
}
This is the code of the class that creates the asteroids:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SterTest extends JFrame implements ActionListener
{
public int a;
public SterTest()
{
this.setSize(700, 700);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
final JPanel p = new JPanel();
p.setBackground(Color.BLACK);
p.setLayout(null);
for(a=0;a<3;a++) {
Astroid astroid = new Astroid(1,1);
p.add(astroid);
} //Creates 3 asteroids to start with
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
Astroid astroid2 = new Astroid(1,1);
p.add(astroid2);
a++;
System.out.println("Het aantal asteroids in game is:"+a);
}
}, 5000, 5000); // creates a new asteroid every 5 seconds or so
this.add(p);
this.setVisible(true);
}
Keeping track of the score probably isn't the job of the Asteroid class, so that variable would be best kept in a more central class. Then you can add an instance of the central class to each asteroid, and call a method to increment the score. Something like this:
public class ScoreKeeper {
private AtomicInteger score;
public void incrementScore (int points) {
score.getAndAdd (points);
}
public int getScore () {
return score.get ();
}
}
In you class SterTest you would create a single instance of ScoreKeeper and pass it to each new Astroid instance you create.
public class Astroid {
private ScoreKeeper scoreKeeper;
public Astroid(int x,int y, ScoreKeeper scoreKeeper) {
//... existing code ...
this.scoreKeeper = scoreKeeper;
}
// ... when you want to increment the score, do this:
scoreKeeper.incrementScore (1);
}
Note: There are better and more OO approaches to this. This answer is that fastest route to working code from your current solution.
Declare score as static.
private static int score
This will give you a single copy of that variable.
However
I see you have some threads. In this case you're going to need a little bit of synchronization to keep score consistent.
I recommend adding
private static final Object scoreLock
to your fields. And replace score++ with
synchronized(scoreLock)
{
Asteroid.score++;
}
If you're not interested in keeping score of an individual asteroid than there is no reason to add a score variable to that class. The score should be maintained at a higher level, perhaps in your SterTest() class. When you detect an asteroid has made it to the bottom, just increment that score. I don't want to tell you how to design your program, but the most obvious way would be to just have actionPerformed return the score.
Create an AsteroidListener interface. Maybe like this:
public interface AsteroidListener {
public void impact(Asteroid asteroid);
}
Make your SterTest class implement this interface. Add a new parameter to your Asteroid constructor, for the listener.
public Asteroid(int x, int y, AsteroidListener listener) { }
When you need to call the listener to notify it that there was an impact:
listener.impact(this);
Tally up the score in your SterTest class.
Use the Java Observer/Observable pattern:
public class Score extends Observable {
private AtomicInteger counter = new AtomicInteger();
public void increment() {
setChanged();
notifyObservers(Integer.valueOf(counter.incrementAndGet()));
}
}
This class is added to Astroid :
public Astroid(Score score, int x,int y) {
// ...
#Override
public void actionPerformed(ActionEvent event) {
// ...
score.increment();
}
}
StarTest implements the Observer interface:
public class StarTest implements Observer {
// ...
#Override
public void update(Observable o, Object arg) {
Integer count = (Inter)arg;
// do something with the score
}
}
You connect Observer and Observable as follows:
StarTest starTest = new StarTest();
Score score = new Score();
score.addObserver(starTest);
Astroid astroid = new Astroid(score, x, y);
I am wondering how would I change the name of the item list in my JComboBox?here's my code
I want to change it to Dog, Panda, bee. rather than choosing their path.
import java.awt.FlowLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JFrame;
import javax.swing.ImageIcon;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JComboBox;
public class ComboTest {
private JLabel imageLabel;
private JComboBox comboImage;
private String[] names = {"images/dog.gif","images/bee.gif","images/Panda.gif"};
private Icon[] icons = {
new ImageIcon(getClass().getResource(names[0])),
new ImageIcon(getClass().getResource(names[1])),
new ImageIcon(getClass().getResource(names[2])),
};
public ComboTest(){
initComponents();
}
public void initComponents(){
JFrame frame = new JFrame("Test Combo");
frame.setVisible(true);
frame.setSize(320, 160);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
comboImage = new JComboBox(names);
comboImage.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent event){
if(event.getStateChange() == ItemEvent.SELECTED){
imageLabel.setIcon(icons[comboImage.getSelectedIndex()]);
}
}
});
frame.add(comboImage);
imageLabel = new JLabel(icons[0]);
frame.add(imageLabel);
}
}
You probably want to make an object with two properties, the path and the text you want to display.
Then you'll set the toString method to return the text property. Disclaimer: I haven't tested any of this code.
public class ValueText {
private String text;
private String value;
public ValueText(final String text, final String value) {
this.text = text;
this.value = value;
}
#Override
public String toString() {
return text;
}
public String getValue() {
return value;
}
}
Then you can change your initial array to something like:
private Object[] names = {
new ValueText("Dog", "images/dog.gif"),
new ValueText("Bee", "images/bee.gif"),
new ValueText("Panda", "images/Panda.gif")
};
And it should work similarly, only now, when you are inspecting the selected item, you can use the getValue() method to get the path.
You also might be interested in a custom renderer, but it's probably not necessary for your use:
http://docs.oracle.com/javase/tutorial/uiswing/components/combobox.html#renderer
Update I'll go ahead and make a correction after kleopatra made some convincing arguments in the comments, which you should read below.
A more general purpose and cleaner way of doing this is with a custom renderer, even if it's very simple (see link above).