hey i have another problem. I created JList in my main window and now i want to add something to it. I do it this way...
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt)
{
Dodaj_Przedmiot dodaj_przedmiot = new Dodaj_Przedmiot(null, true);
dodaj_przedmiot.setVisible(true);
SterowanieBazy instance = SterowanieBazy.getInstance();
Zmienne_pomocnicze zp = new Zmienne_pomocnicze();
String przedmiot = zp.getPrzechowaj();
instance.dodajPrzedmiot(przedmiot);
String przedm[] = instance.zwrocPrzedmioty();
jList1.setListData(przedm);
}
what i want to write in that list is what i collect from my jDialogForm: dodaj_przedmiot
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
String sciezka = jTextField1.getText();
if (sciezka.length() > 0)
{
Zmienne_pomocnicze zp = new Zmienne_pomocnicze();
zp.setPrzechowaj(sciezka);
}
this.setVisible(false);
}
and i collect try to copy that date using this class
public class Zmienne_pomocnicze {
public String n;
public int a;
public void setPrzechowaj (String neew)
{
n = neew;
}
public String getPrzechowaj ()
{
return n;
}
}
i would be grateful for any ideas how to make it work.
This is somewhat difficult to follow, but from what I gather, you are using your Zmienne_pomocnicze class in two places, and both of them seem to do nothing.
First, in jButton2ActionPerformed you instantiate a new Zmienne_pomocnicze and try to get the data from it using the getPrzechowaj method. This will return n, but as you have just instantiated the instance, n is null. As I cant infer from the method names of the following code, I cant figure out what you want to do with that data, but this action is most certainly not what you want to do.
In the second case, jButton1ActionPerformed takes the value from the text field and then test for validity (legnth is greater than 0). If the validation passes, you then create a new Zmienne_pomocnicze, call setPrezechowaj with the text field value and then let the new object fall out of scope. Again, this is certainly not the desired effect.
It would be interesting to see what the flow of your program is supposed to be, ie what button triggers which jButton[12]ActionPerformed methods and how you expect them to interact.
Here's a simple example of adding entries to a JList.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.*;
public class JListTest {
private static final Random random = new Random();
public static final void main(String args[]) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
final JFrame frame = new JFrame("Test");
final DefaultListModel dlm = new DefaultListModel();
final JList list = new JList(dlm);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(new JScrollPane(list));
frame.add(new JButton("Add") {
{
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dlm.addElement("A" + (random.nextInt(9000) + 1000));
}
});
}
}, BorderLayout.SOUTH);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
}
I always recommend reading the API for basic information.
If you read the JList API you will find a link to the Swing tutorial on "How to Use Lists". The example there shows how to dynamically add and remove entries from the ListModel.
Tutorials are a good place to start because you find working examples as well as explanations as to how the code works. Then, if required you can ask a specific question about a specific piece of code.
Not only that you now have a reference that might come in handy for other problems.
Related
I'm having an issue when I try to display a JList with an ArrayList. I'm using Action Listeners to execute all this:
ContactArray contactObject = new ContactArray();
addContactBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String firstName = firstNameField.getText();
String lastName = lastNameField.getText();
contactObject.addName(firstName + " " + lastName);
// contactObject.getNames().forEach(System.out::println);
}
});
viewContactButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String[] contacts = contactObject.getNames().toArray(new String[0]);
contactList = new JList(contacts);
contactList.setVisibleRowCount(5);
contactList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
add(new JScrollPane(contactList));
}
});
ContactArray class:
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class ContactArray {
private List<String> names;
public ContactArray() {
this.names = new ArrayList<>();
}
//add a name to list
public void addName(String name) {
if (!Objects.nonNull(names)) {
this.names = new ArrayList<>();
}
this.names.add(name);
}
//get the name attribute
public List<String> getNames() {
if (!Objects.nonNull(names)) {
this.names = new ArrayList<>();
}
return this.names;
}
}
I have managed to print the full names to the console with contactObject.getNames().forEach(System.out::println);which I put in comments, but can't seem to add them to JList. Normally, when I press on viewContactButton, it should display it.
Also, I'm using the Swing GUI form from IntelliJ IDEA.
Thanks for any help :)
I have managed to print the full names to the console
Well, you placed that code in the wrong place. The code should be placed when you actually use the List to create the JList. (ie. Maybe you have code somewhere that accidentally deletes the List sometime after it is created and before it is used)
I'm having an issue when I try to display a JList with an ArrayList
Well is the problem the ArrayList or did you also try to hardcode data in the JList? In order to solve a problem you need to know what the real problem is. Always first try to display hard coded data instead of dynamic data.
add(new JScrollPane(contactList));
I would guess the real problem is the above statement.
Whenever you add components to a visible frame the basic code should be:
add(...);
revalidate();
repaint();
You need to invoke the layout manager of the panel. Otherwise the component has a size of 0, so there is nothing to paint.
I've looked around but nothing seems to help me out. Basically I'm writing a multithreaded chat program with a gui. The user inputs his name in a textfield in a Login class and hits the login button which directs him to a ClientGUI class. In the client GUI class theres a JLabel at the top that says
"Welcome to the ChatSystem (Username)"
. So what the user input in the textfield in the login class should appear in the JLabel after "Welcome to the ChatSystem" but I can't figure out why it doesn't work. Here's my code:
Login Class:
loginB = new JButton("Login");
main.add(loginB);
loginB.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
ClientGUI clientgui = new ClientGUI();
clientgui.setVisible(true);
}
}
ClientGUI class:
public ClientGUI(){
Login login = new Login();
String username = login.usernameTF.getText();
welcome = new JLabel("Welcome to ChatSystem "+username, SwingConstants.CENTER);
}
I understand that username should really by a JLabel and not a String but I have tried many ways to do this and I can't seem to get my head around this.
That is not going to work like that because
login.usernameTF.getText(); is actually a new created object in the ClientGUI constructor...
what I would suggest to do is to overload the constructor and to pass the name as parameter...
Example:
loginB.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
ClientGUI clientgui = new ClientGUI(getTheNameAndpassItHere);
clientgui.setVisible(true);
}
}
and then ClientGUI class:
public ClientGUI(String username){
//Login login = new Login();
// String username = login.usernameTF.getText();
welcome = new JLabel("Welcome to ChatSystem "+username, SwingConstants.CENTER);
}
Basically, you should use a Observer Pattern, which allows ClientGUI to generate events to interested parties when something changes.
This decouples your code and prevents the ClientGUI from doing things it shouldn't (like removing the label or it's parent component for example)
You could use some of the inbuilt listeners if they meet your needs, but for something like this, I'd prefer to use my own
public class LoginEvent extends EventObject {
private Throwable cause;
private String userName;
public LoginEvent(Object source) {
super(source);
}
public Throwable getCause() {
return cause;
}
public String getUserName() {
return userName;
}
}
public interface LoginListener extends EventListener {
public void loginFailed(LoginEvent evt);
public void loginSuccessful(LoginEvent evt);
}
Then you could add an instance of the listener to the ClientGUI...
loginB.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
ClientGUI clientgui = new ClientGUI(getTheNameAndpassItHere);
clientgui.addLoginListener(new LoginListener() {
#Override
public void loginFailed(LoginEvent evt) {
Throwable cause = evt.getCause();
// Show error message
}
#Override
public void loginSuccessful(LoginEvent evt) {
String name = evt.getUserName();
// Update UI
}
});
clientgui.setVisible(true);
}
}
or something simular
the swings component are by default private you need to make them public by just little steps
1.go to the properties of the component and then to the code tab
2.you will find variable modifier as private make them public and as well as static if you want.
you will now be able to use the components with the same code
I'm trying to create a custom JSpinner that represents a sequence of numbers of power 2. Like, 1-2-4-8-16 and so on. I have to do that with extending AbstractSpinnerModel and changing its implemented methods (getNextValue etc.). The problem is, the arrow keys on my custom JSpinner don't work. Nothing changes when I click one of them. I need to show previous and next values of current value. ( Previous value = 4 Current Value = 8 Next Value = 16 ).
Here is my code :
import java.awt.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Hw5SpinnerModel extends JFrame {
public static void main(String[] args) {
Hw5SpinnerModel frame = new Hw5SpinnerModel();
}
public Hw5SpinnerModel() {
setTitle("Hw5SpinnerModel");
setSize(350, 300);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JSpinner jspn = new JSpinner(new CustomSpinnerModel());
final JLabel jlbl = new JLabel("");
add(jspn, BorderLayout.NORTH);
add(jlbl, BorderLayout.CENTER);
jspn.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
jlbl.setText(jspn.getPreviousValue() + jspn.getValue() + jspn.getNextValue());
}
});
//jlbl.setText(jspn.getNextValue() + "");
setVisible(true);
}
public class CustomSpinnerModel extends AbstractSpinnerModel {
Integer i = 1;
#Override
public Object getValue() {
return i;
}
#Override
public void setValue(Object value) {
i = (Integer) value;
}
#Override
public Object getNextValue() {
return 2 * i;
}
#Override
public Object getPreviousValue() {
return i / 2;
}
}
}
Any help will be appreciated.
jSpinner1.setModel(new SpinnerNumberModel(1, null, null, 1) {
#Override
public Object getNextValue() {
Object nextValue = super.getValue();
int x = Integer.valueOf(nextValue.toString())*2;
//Object o = x;
return x;
}
});
It works 100%
I had this problem this week, and here's the answer to your question: The JSpinner operates through the use of ChangeListeners, and those ChangeListeners need to be activated when the model's value changes.
You may have had difficulty finding this (as I did), because you thought that getNextValue and getPreviousValue, in your custom class, were returning bad values. They aren't; but the JSpinner just doesn't use them directly. It feeds them straight back to the SpinnerModel through setValue.
(Except if getNextValue or getPreviousValue return null, which is a special case. Then the JSpinner does nothing.)
So, in code, your setValue function needs a fireStateChanged call after the change to i:
#Override
public void setValue(Object value) {
i = (Integer) value;
fireStateChanged ();
}
You might think that the JSpinner shouldn't operate this way, and should take the value from getNextValue and getPreviousValue to display immediately, instead of this indirect process. But the JSpinner has to call setValue in any case, and setValue has to notify the ChangeListeners in any case (because a single model can be passed around to many places in your program).
For instance, if you had two JSpinners in different places, with the same SpinnerModel, then changes to the model need to be reflected on both JSpinners, but only one JSpinner gets to call getNextValue or getPreviousValue at one time.
I have a JTextField and a JList in my program. The JList contains the user's contacts. I'd like to filter the JList based on the text on the JTextField. For example, if I type in "Mike" it will only show contacts including "Mike". When the user clears the JTextField it would reset the filter.
I know I could do this manually by having two arrays. One for the original contacts and one for the filtered ones. When the user changes the value of the JTextField I would go trought the original list, update the temporary list and update the JList. I just wonder if there is some built in feature to avoid manual labour.
The best way to do things like that is to have a ListModel implementation that filters its contents.
I don't know of any default filtering ListModel implementations, but it should not be too hard to do.
Here's a quick and dirty solution just to give you an idea. You might want to add more bells and whistles to it.
package test;
import java.util.ArrayList;
import javax.swing.AbstractListModel;
import javax.swing.ListModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
public class FilteredListModel extends AbstractListModel {
public static interface Filter {
boolean accept(Object element);
}
private final ListModel _source;
private Filter _filter;
private final ArrayList<Integer> _indices = new ArrayList<Integer>();
public FilteredListModel(ListModel source) {
if (source == null)
throw new IllegalArgumentException("Source is null");
_source = source;
_source.addListDataListener(new ListDataListener() {
public void intervalRemoved(ListDataEvent e) {
doFilter();
}
public void intervalAdded(ListDataEvent e) {
doFilter();
}
public void contentsChanged(ListDataEvent e) {
doFilter();
}
});
}
public void setFilter(Filter f) {
_filter = f;
doFilter();
}
private void doFilter() {
_indices.clear();
Filter f = _filter;
if (f != null) {
int count = _source.getSize();
for (int i = 0; i < count; i++) {
Object element = _source.getElementAt(i);
if (f.accept(element)) {
_indices.add(i);
}
}
fireContentsChanged(this, 0, getSize() - 1);
}
}
public int getSize() {
return (_filter != null) ? _indices.size() : _source.getSize();
}
public Object getElementAt(int index) {
return (_filter != null) ? _source.getElementAt(_indices.get(index)) : _source.getElementAt(index);
}
}
In order to use it you need to set it to your JList and then call setFilter() as you need.
Here's an example:
ListModel source = new DefaultListModel(); // use a model of your choice here;
FilteredListModel filteredListModel = new FilteredListModel(source);
JList list = new JList(filteredListModel);
filteredListModel.setFilter(new FilteredListModel.Filter() {
public boolean accept(Object element) {
return false; // put your filtering logic here.
}
});
Once method setFilter() is invoked your JList on the screen is expected to change its contents accordingly.
Alternatively, you may want to implement an observer/observable pattern for your Filter, so you can re-filter the list without calling method setFilter(). You can experiment with that later. For the first iteration it's good enough as long as you call method setFilter every time user types something in your JTextField.
A simpler solution might be to use JTable, which does have a built-in ability to filter and sort (RowSorter). A single-column table is not too different from a list.
If you're okay with external libs, I would recommend Jide's QuickListFilterField/QuickTreeFilterField. With few lines of code, you could get a visually filterable JList/JTree, case sensitive/insensitive search, wildcard/regex matching etc ... Amazingly easy to use !
I'm a newbie in java and I have a small problem. I want to access a variable in one class from another. I have three classes and I want to be able to access a variable in the main class to enable me read the array.
The error I am getting is
java.lang.SecurityException: MIDlet not constructed by createMIDlet
Please see the example below. Please bear in mind they're all in the same package.
package tungPackage;
import com.sun.lwuit.*;
import com.sun.lwuit.animations.CommonTransitions;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import javax.microedition.midlet.MIDlet;
public class TungMidlet extends MIDlet implements ActionListener {
private Command back = new Command("Back");
private Command ok = new Command("Ok");
public ActionListener commandlistListener = new ActionListener() {
public void actionPerformed(ActionEvent cmd) {
// check which command cliked
if (cmd.getCommand() == back) {
// go back to previous form
mainForm.show();
} else if (cmd.getCommand() == ok) {
// go forward
}
}
};
private List list;
private Form mainForm;
private Label promptLabel;
private housesClass houseClassObject = new housesClass();
public int counter; //this is the variable I want to access in a class called calculate class object.
private int sumAmmt;
public TungMidlet tungMidletObject;
public calculateClass calculateClassObject;
public TungMidlet() {
Display.init(this);
}
private ActionListener applistListener = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if(list.getSelectedIndex()==0){
counter++;
if (counter>5)
{
//check sum price.
sumAmmt = calculateClassObject.calculateSum();
Dialog x = new Dialog("info");
Label label = new Label("Maximum reached.");
Label label2 = new Label("Sum ammt = "+sumAmmt);
x.addComponent(label);
x.addComponent(label2);
x.addCommand(ok);
x.show();
}
else
{
//calculate the price
String info = houseClassObject.randomHouse();
Dialog x = new Dialog("info");
Label label = new Label(info);
x.addComponent(label);
x.addCommand(ok);
x.show();
}
}
}
};
public void startApp() {
//calculateClassObject = new calculateClass();
//sumAmmt = calculateClassObject.calculate(sumAmmt);
mainForm = new Form("Investment Categories");
promptLabel = new Label("choose category");
list = new List();
list.addItem("House");
list.addItem("Cars");
list.addItem("Schools");
list.addItem("Schools");
list.addItem("Supermarkets");
list.addItem("Stocks");
list.addItem("Land");
list.addActionListener(applistListener);
mainForm.addComponent(promptLabel);
mainForm.addComponent(list);
mainForm.addCommand(back);
mainForm.addCommandListener(commandlistListener);
mainForm.setTransitionInAnimator(CommonTransitions.createSlide(CommonTransitions.SLIDE_HORIZONTAL, true, 1000));
mainForm.show();
}
public void pauseApp() {}
public void destroyApp(boolean unconditional) {}
public void actionPerformed(ActionEvent ae) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
The class I want to access the "counter" variable using is shown below.
package tungPackage;
import java.util.Random;
public class housesClass {
public Random generator = new Random();
public String[] houseArray = new String[5];
public housesClass housesClassObject;
public calculateClass calcobj;// = new calculateClass();
public housesClass()
{
}
public String randomHouse() {
housesClassObject = new housesClass();
houseArray[0] = "Bungalow - 20,000,000 Shillings";
houseArray[1] = "Microhouse - 10,000,000 Shillings";
houseArray[2] = "Flat - 200,000,000 shillings";
houseArray[3] = "Garage apartment - 7,000,000 shillings";
houseArray[4] = "Studio apartment - 13,000,000 shillings";
int rnd = generator.nextInt(houseArray.length);
housesClassObject.housePrices(rnd);///noma
String house = houseArray[rnd];
return house;
}
void housePrices(int houseNumber) {
calcobj = new calculateClass();
TungMidlet tungmidobj = new TungMidlet();
int counter = tungmidobj.counter;
int[] housePriceArray = new int[5];
housePriceArray[0] = 20000000;
housePriceArray[1] = 10000000;
housePriceArray[2] = 200000000;
housePriceArray[3] = 7000000;
housePriceArray[4] = 13000000;
int price = housePriceArray[houseNumber];
calcobj.storePrice(counter,price);
}
}
The other supporting class is shown below.
package tungPackage;
public class calculateClass {
int[] storeArray = new int[5];
public calculateClass()
{
}
public void storePrice(int counter, int number2)
{
storeArray[counter] = number2;
}
public int calculateSum()
{
int sum =0;
for(int i=1; i<6; i++){
sum= sum+storeArray[i];
}
return sum;
}
}
Are you getting an error? It looks like your access code should work.
I can't seem to find anywhere that you actually initialise counter though, so maybe your problem is that you need to put counter = 0; somewhere in your code.
Java is also object oriented so you should avoid accessing like the above and make some 'getter and setter' methods:
public int getCounter() {
return counter;
}
and then call int counter = tungmidobj.getCounter();
remove TungMidlet constructor. If there was something useful to do there, you could also declare it protected - but this is not the case with your code snippet, see below.
Wherever you try to invoke that constructor directly, remove code that does this and find another way to do what you need. If needed, study code examples provided in LWUIT Tutorial - Introduction for how typical things are done in LWUIT.
put statement Display.init() in the beginning of the startApp method,
just like it is done in LWUIT Tutorial - Hello, LWUIT! example code
The reason why you are getting SecurityException is because you invoke TungMidlet constructor directly. Don't do that.
MIDP API documentation for MIDlet constructor states:
Throws:
SecurityException - unless the application management software is creating the MIDlet.
one way is
TungMidlet tungMidlet=new TungMidlet();
System.out.println(tungMidlet.counter);
but know encapsulation
second way is
you can make counter private variable and provide setter and getters.
private int counter;
public void setCounter(int counter){
this.counter=counter;
}
public int getCounter(){
return counter;
}
second way is preferred way as it achieves encapsulation