Referencing JRadioButtons in ActionListener - hashmap

I am trying to write a GUI that displays a hex value and it's associated color based on whichever JRadioButton is selected. My ActionListener looks up a hashMap entry that stores the individual radio buttons as an object key and it's associated hex value (as a string).
I can get the hex values with the hashMap.get pieces, but how do I get the action listener to reference any JRadioButton rather than just 'jrbBlue' or whatever is hard-coded?
Eclipse doesn't like it if I put JRadioButton.addActionListener(Error - "Cannot make a static reference to the non-static method addActionListener(ActionListener) from the type AbstractButton") or jpRadioButton.addActionListener, my JPanel for the buttons (it wants to change addActionListener to addComponentListener and a bunch of other addWhatevers, none of which work).
I realize there are other ways to write this whole thing, but I'm tying to work with what I have and I'm still learning.
Thanks in advance.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
public class Colors extends JFrame {
static Map<Object, String> hashMap = new HashMap<Object, String>();
String hex = "Hex Value";
//---- The JLabel message (hex value of the color selected)
private JLabel jlblMessage = new JLabel(hex, JLabel.CENTER);
//---- Create the radio buttons
private static JRadioButton jrbBlue = new JRadioButton("Blue");
private static JRadioButton jrbPurplish = new JRadioButton("Purplish");
private static JRadioButton jrbRed = new JRadioButton("Red");
private static JRadioButton jrbYellow = new JRadioButton("Yellow");
private static JRadioButton jrbGreen = new JRadioButton("Green");
private static JRadioButton jrbOrange = new JRadioButton("Orange");
private static JRadioButton jrbCyan = new JRadioButton("Cyan");
private static JRadioButton jrbCoral = new JRadioButton("Coral");
private static JRadioButton jrbFuscia = new JRadioButton("Fuscia");
private static JRadioButton jrbViolet = new JRadioButton("Violet");
private static JRadioButton jrbDodgerBlue = new JRadioButton("Dodger Blue");
private static JRadioButton jrbGrey = new JRadioButton("Grey");
private static JRadioButton jrbWhite = new JRadioButton("White");
private static JRadioButton jrbCrimson = new JRadioButton("Crimson");
private static JRadioButton jrbDarkOrchid = new JRadioButton("Dark Orchid");
private static JRadioButton jrbFirebrick = new JRadioButton("Firebrick");
private static JRadioButton jrbHotPink = new JRadioButton("Hot Pink");
private static JRadioButton jrbMaroon = new JRadioButton("Maroon");
private static JRadioButton jrbDarkBlue = new JRadioButton("Dark Blue");
private static JRadioButton jrbTurquoise = new JRadioButton("Turquoise");
public Colors() {
//---- JLabel placement
jlblMessage.setBorder(new LineBorder(Color.BLACK, 2));
add(jlblMessage, BorderLayout.CENTER);
//---- Add the radio buttons to the JPanel
JPanel jpRadioButtons = new JPanel();
jpRadioButtons.setLayout(new GridLayout(3, 1));
jpRadioButtons.add(jrbBlue);
jpRadioButtons.add(jrbPurplish);
jpRadioButtons.add(jrbRed);
jpRadioButtons.add(jrbYellow);
jpRadioButtons.add(jrbGreen);
jpRadioButtons.add(jrbOrange);
jpRadioButtons.add(jrbCyan);
jpRadioButtons.add(jrbCoral);
jpRadioButtons.add(jrbFuscia);
jpRadioButtons.add(jrbViolet);
jpRadioButtons.add(jrbDodgerBlue);
jpRadioButtons.add(jrbGrey);
jpRadioButtons.add(jrbWhite);
jpRadioButtons.add(jrbCrimson);
jpRadioButtons.add(jrbDarkOrchid);
jpRadioButtons.add(jrbFirebrick);
jpRadioButtons.add(jrbHotPink);
jpRadioButtons.add(jrbMaroon);
jpRadioButtons.add(jrbDarkBlue);
jpRadioButtons.add(jrbTurquoise);
add(jpRadioButtons, BorderLayout.WEST);
//---- Add all the buttons to the same group
ButtonGroup group = new ButtonGroup();
group.add(jrbBlue);
group.add(jrbPurplish);
group.add(jrbRed);
group.add(jrbYellow);
group.add(jrbGreen);
group.add(jrbOrange);
group.add(jrbCyan);
group.add(jrbCoral);
group.add(jrbFuscia);
group.add(jrbViolet);
group.add(jrbDodgerBlue);
group.add(jrbGrey);
group.add(jrbWhite);
group.add(jrbCrimson);
group.add(jrbDarkOrchid);
group.add(jrbFirebrick);
group.add(jrbHotPink);
group.add(jrbMaroon);
group.add(jrbDarkBlue);
group.add(jrbTurquoise);
//jrbBlue.setSelected(true);
//jlblMessage.setForeground(Color.decode("#0000FF"));
//---- Action Listener
jrbBlue.addActionListener(new ActionListener() { //<---- How to Reference whichever button is selected?
#Override
public void actionPerformed(ActionEvent e) {
jlblMessage.setForeground(Color.decode("#000000"));
jlblMessage.setText(hashMap.get((JRadioButton)e.getSource()));
getContentPane().setBackground(Color.decode(hashMap.get((JRadioButton)e.getSource())));
}
});
}
public static void main(String[] args) {
Colors frame = new Colors();
frame.pack();
frame.setTitle("Colors");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(900,300);
//---- Color library map
hashMap.put(jrbBlue, "#0000FF");
hashMap.put(jrbPurplish, "#DF01D7");
hashMap.put(jrbRed, "#FF0000");
hashMap.put(jrbYellow, "#FFFF00");
hashMap.put(jrbGreen, "#00FF00");
hashMap.put(jrbOrange, "#FF8C00");
hashMap.put(jrbCyan, "#00FFFF");
hashMap.put(jrbCoral, "#FF7F50");
hashMap.put(jrbFuscia, "#FF00FF");
hashMap.put(jrbViolet, "#00FF00");
hashMap.put(jrbDodgerBlue, "#1E90FF");
hashMap.put(jrbGrey, "#C0C0C0");
hashMap.put(jrbWhite, "#FFFFFF");
hashMap.put(jrbCrimson, "#DC143C");
hashMap.put(jrbDarkOrchid, "#9932CC");
hashMap.put(jrbFirebrick, "#B22222");
hashMap.put(jrbHotPink, "#FF69B4");
hashMap.put(jrbDarkBlue, "#00008B");
hashMap.put(jrbMaroon, "#800000");
hashMap.put(jrbTurquoise, "#48D1CC");
}
}

Write a single action listener and add it to all required radio buttons. Then inside actionPerformed(ActionEvent e), you can call e.getSource(). This returns the corresponding JRadioButton, so you can cast it and use it. No need to hardcode variables inside the action listener.

Related

Android studio room database - not returning values in onRestart() method

My app is a list of element names. Clicking one goes to another activity with more details, and an editText and button to change its name. When I go back to the list, I want it to have the new name if updated. My onCreate method has this code which populates it from the database perfectly (ignore the hardcoded size, its just simpler for debugging)
final String DATABASE_NAME = "element_db";
final AppDatabase appDatabase;
appDatabase = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, DATABASE_NAME).build();
ListView list = (ListView)findViewById(R.id.listView);
final String[] element = new String[3];
new Thread(new Runnable() {
#Override
public void run() {
List<Element> elements;
elements = appDatabase.elementDao().fetchElements(); // a dao query "select*from"
int size = elements.size();
for (int i = 0; i < size; i++){
element[i] = elements.get(i).getName();
}
}
}) .start();
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, R.layout.activity_list_view, R.id.textView, element);
list.setAdapter(arrayAdapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent i = new Intent(MainActivity.this, itemdetail.class);
i.putExtra("pos", position);
startActivity(i);
}
});
To achieve an updated list when returning to this screen, I copied the above code into the onRestart method, but now the database does not return anything. If I just set the array that goes into the adapter to {"a", "a", "a"} the list populates fine. Any ideas why the database works onCreate but not onRestart?
I think you can use ViewModel and livedata to observe any database change

during execution master detail flow i get 2 errors 1-Error:(77, 24) error: cannot find symbol class ItemListActivity

public static class SimpleItemRecyclerViewAdapter
extends RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder> {
private final ItemListActivity mParentActivity;
private final List<DummyContent.DummyItem> mValues;
private final boolean mTwoPane;
private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
DummyContent.DummyItem item = (DummyContent.DummyItem) view.getTag();
if (mTwoPane) {
Bundle arguments = new Bundle();
arguments.putString(WebpageDetailFragment.ARG_ITEM_ID, item.id);
WebpageDetailFragment fragment = new WebpageDetailFragment();
fragment.setArguments(arguments);
mParentActivity.getSupportFragmentManager().beginTransaction()
.replace(R.id.webpage_detail_container, fragment)
.commit();
This happens when you change the default item names during the wizard of creating the activity.
just rename the ItemListActivity to the name of your Activity . ( the name of the file that has that code error).
use refactor rename to change it everywhere it's mentioned.
If the ItemListActivity (or whatever you ended up calling it) extends from Activity and not AppCompatActivity then try changing the line
mParentActivity.getSupportFragmentManager().beginTransaction()
to
mParentActivity.getFragmentManager().beginTransaction()

Need to set additional information in list view

I am trying to created a listview containing filenames. I want to set a additional information like file id with each list items, so when i click a filename, i have to get file id from it. please help me do this.
My sample code:
ListView listview = (ListView) findViewById(R.id.listview);
ArrayAdapter fileListAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, ['one','two','three']);
listview.setAdapter(fileListAdapter);
There are quite a few things involved here, so i'm providing you with an example of how you can achieve this (you can copy-paste and test):
public class MainActivity extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// First we simulate a pool of file names and IDs
String[] fileNames = {"fileName1", "fileName2", "fileName3"};
List<Integer> fileNameIds = new ArrayList<Integer>();
fileNameIds.add(1200);
fileNameIds.add(356);
fileNameIds.add(28);
// We call our custom Adapter
ArrayAdapter<String> adapter = new CustomAdapter(this, fileNames, fileNameIds);
// Finally we set the adapter to our list
setListAdapter(adapter);
}
// This is a custom adapter that uses ArrayAdapter for our purpose
// (as this is just an example you should consider using Base Adapter if you don't want
// to have a pool of filenames and a separate pool of ids)
class CustomAdapter extends ArrayAdapter<String>{
private final LayoutInflater INFLATER;
private final String[] FILE_NAMES;
private final List<Integer> FILE_NAME_IDS;
public CustomAdapter(Context context, String[] fileNames, List<Integer> fileNameIds) {
super(context, R.layout.custom_row, fileNames);
this.INFLATER = LayoutInflater.from(context);
this.FILE_NAMES = fileNames;
this.FILE_NAME_IDS = fileNameIds;
}
// HERE is where you can assign effectively an ID to your rows
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// this is an object that takes advantage of the holder pattern
// it retains the state of our rows in the list
FileNameHolder holder;
if(convertView == null){
convertView = INFLATER.inflate(R.layout.custom_row, null); // inflate your custom row
// now you need to assign specific identifier to the list row that the holder will retain
// for you, so you can always get this id by calling getTag from the View object on your
// item click listeners
holder = new FileNameHolder();
holder.fileName = (TextView) convertView; //since i only have a texView in layout i don't need to call findByView
convertView.setTag(holder); // relate the view to a custom FileNameHolder object that retains file name and its ID
} else{
holder = (FileNameHolder) convertView.getTag();
}
holder.fileName.setText(FILE_NAMES[position]); // PROVIDE the list with file name description
holder.idFileName = FILE_NAME_IDS.get(position); // ASSIGN file name ID
return convertView;
}
}
// This is an example of catching a row clicked and get the custom ID that you assigned,
// from here you can use that ID as you need
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// Here as you can see we obtain the object associated with the row that was clicked
FileNameHolder holder = (FileNameHolder) v.getTag();
// Here i provide a way you can test that you're always getting the correct file name and Id
Toast.makeText(this,
"File Name = " + holder.fileName.getText() +
", File ID = " + holder.idFileName,
Toast.LENGTH_SHORT).show();
}
// This is a class that takes advantage of the Holder Pattern and we use it to
// achieve what you need (remember this is just an example you should consider
// changing class and member access modifiers as you need)
class FileNameHolder{
Integer idFileName;
TextView fileName;
FileNameHolder() {
}
}
}
custom_row.xml is just a TextView (i took it from the simple_list_item_1 layout):
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:paddingStart="?android:attr/expandableListPreferredItemPaddingLeft"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center_vertical"
/>
Hope it's useful... regards!!

Pass object from one scene to another

As I'm learning the new world of JavaFX2 I stumbled on another annoying problem. I'm developing a program with multiple scenes (~10 scenes). For that I created a small class like this:
public class SceneSelector {
...
public void setScene(Stage stage, String fxmlfilename, ObservableList ol) throws Exception{
String s = "../" + fxmlfilename;
Parent root = FXMLLoader.load(getClass().getResource(s));
root.setUserData(ol);
Scene scene = new Scene(root);
stage.setScene(scene);
//show the stage
stage.show();
}
}
This class works good enough for switching between the scenes.
Now the problem is that I sometimes need to pass data from Scene1 to Scene2. I'm trying to do this by setting the setUserData() for the new scene which basicly works exept for one thing. How can I get the userdata when the new Scene is beeing initialized? (because the Nodes are still null at that time)
Code at scene1:
//Code connected to a button that opens the new Scene
private void openLabID(ActionEvent event) throws Exception {
final Stage primaryStage = (Stage) btnNewScene.getScene().getWindow();
ObservableList<Koe> olAfTeWerkenKoeien = DA_Koe.getAfTeWerkenKoeien();
ss.setScene(primaryStage, "GUI/scenes/koe/Koe.fxml", olAfTeWerkenKoeien);
}
Code at scene2:
public void initialize(URL url, ResourceBundle rb) {
Scene s = lbl.getScene();
ObservableList<Koe> olAfTeWerkenKoeien = (ObservableList<Koe>) s.getRoot().getUserData();
System.out.println(olAfTeWerkenKoeien.size());
}
Of course Scene s gives a null value at this point (because lbl is null at this point), so I wonder, is there a method that is beeing fired right after initialize?
When I attach this code to a button on Scene2, it works like a charm, but it should be loaded automatically.
EDIT:
The setting of the data with the setMyData() method is not a problem, however retrieving it is:
public ObservableList<Koe> getMyData() {
return this.myData;
}
How can I get the CustomScene object when a controller initializes? Because doing this below will result in a NullPointerException (because btnSluiten is not initialized just yet):
#Override
public void initialize(URL url, ResourceBundle rb) {
...
Stage stage = (Stage) btnSluiten.getScene().getWindow();
CustomScene cs = (CustomScene) stage.getScene();
ObservableList<Koe> olKoe = cs.getMyData();
System.out.println(olKoe.size());
}
I believe you missed the point within the Scene object. From the Scene class documentation we can see that:
The JavaFX Scene class is the container for all content in a scene graph.
Which means that the Scene object is just a container and as such it's not supposed to hold any data.
With that in mind, you can make another static object with a field such as
private static Label lbl;
...
public static Label getLbl()
{
return MyStaticObject.Lbl;
}
...
and use it to store your lbl (or whatever object suits your information) and then statically retrieve it.
I'm doing that to set the owner of my other Stage objects from my application. I hope it helps. Cheers
If you really want your scene to be meaningful (aka store specific user data) you can extend it:
public class FooScene extends Scene {
private ObservableList myData;
public setMyData(ObservableList data) {
this.myData = data;
//handle data
}
}
The easiest way to make sure setup code is called after scene initialized it to call it by yourself:
public class SceneSelector {
...
public void setScene(Stage stage, String fxmlfilename, ObservableList ol) throws Exception{
String s = "../" + fxmlfilename;
Parent root = FXMLLoader.load(getClass().getResource(s));
// first: add root to scene
FooScene scene = new FooScene(root);
// second: apply data to scene (or root)
scene.setMyData(ol);
stage.setScene(scene);
//show the stage
stage.show();
}
}
You can use controller for scenes and pass the data through controller:
String filePath1 = "../" + fxmlfilename;
URL location1 = YourController1.class.getResource(filePath1);
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(location1);
fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());
Parent root = (Node) fxmlLoader.load(location1.openStream());
YourController1 ctrl1 = (YourController1) fxmlLoader.getController();
Then you can assign data to the controller:
ctrl1.setUserData();
Finally, just show the scene as you want:
Scene scene = new Scene(root);
stage.setScene(scene);
//show the stage
stage.show();
In the initialize() method in the controller, just get data from controller as usual data object.
Some Addition of #Sergey Grinev :
Create A custom Scene :
package sample;
import javafx.scene.Parent;
import javafx.scene.Scene;
public class DataPassingScene extends Scene {
public DataPassingScene(Parent parent) {
super(parent);
}
String tafsir;
public String getTafsir() {
return tafsir;
}
public void setTafsir(String tafsir) {
this.tafsir = tafsir;
}
}
Suppose your Main Class Name is App.java, Then Create a method to show new Stage :
public static void showLayout (Stage primaryStage, String fxmlFileName, String stringData) throws IOException {
Parent root = FXMLLoader.load(Objects.requireNonNull(App.class.getClassLoader().getResource(fxmlFileName)));
DataPassingScene scene = new DataPassingScene(root);
scene.setTafsir(stringData); // Here we pass the data
primaryStage.setScene(scene);
primaryStage.show();
}
Now When you want to pass the Data, Call the above method from any Where / any class in your app with some Data :
String tafsir = "This My Data" ;
try {
App.showLayout(new Stage(), "showTafsirFxml.fxml",tafsir);
} catch (IOException e) {
e.printStackTrace();
}
Then Get the data in your controller. To get the scene you have to get the stage, and to get the stage you have use one of your elements of FXML, suppose here your element is a button, called closeButton, So :
#FXML
private Button closeButton;
#Override
public void initialize(URL url, ResourceBundle rb) {
Platform.runLater(new Runnable() {
#Override public void run() {
Stage stage = (Stage) closeButton.getScene().getWindow();
DataPassingScene scene = (DataPassingScene) stage.getScene();
String s = scene.getTafsir(); // Here we get the Data
if(s!=null)
System.out.println("This is Tafsir From Highlight Table: "+s);
else
System.out.println("Data Passing Null");
}});
}
because, You have to wait some Times in above runLater, because for initializing scene take some time. Other wise scene will be null.

SmartGWT - Cannot change configuration property "x" after the component created

From this example http://www.smartclient.com/smartgwt/showcase/#tree_databinding_local , I started to implement my own tree structure dynamically (TreeGrid). When I try to render it, I get this error (title).
public class ProjectTreeGridScreen extends Screen {
Tree tree;
#Override
protected void onLoad() {
super.onLoad();
TreeGrid treeGrid = new TreeGrid();
setPageTitle(Util.C.projectListTitle());
treeGrid.setWidth(600);
treeGrid.setHeight(400);
TreeGridField projectTree = new TreeGridField("ProjectName", "Project Tree");
TreeGridField projectPath = new TreeGridField("ProjectPath", "Complete path");
TreeGridField projectDescription = new TreeGridField("ProjectDescription", "Description");
TreeGridField projectInfo = new TreeGridField("ProjectInfo", "Information");
treeGrid.setFields(projectTree, projectPath, projectDescription, projectInfo);
treeGrid.setData(tree);
add(treeGrid);
}
#Override
protected void onInitUI() {
super.onInitUI();
tree = new Tree();
tree.setModelType(TreeModelType.PARENT);
tree.setNameProperty("ProjectName");
tree.setIdField("ProjectItem");
tree.setParentIdField("ProjectParent");
tree.setShowRoot(true);
populateProjects();
}
protected void populateProjects() {
Util.PROJECT_SVC.visibleProjects(
new ScreenLoadCallback<List<Project>>(this) {
#Override
public void preDisplay(final List<Project> result) {
tree.setData(ProjectTreeGridBuilder.fromRepositories(result));
}
});
}
}
what do you mean by "x"? Normally, If a component has been drawn on the window (implicit or explicit call to draw), you cannot change it's properties values. So the only possible solution is to recreate the object with the new X value each time it is changing.

Resources