I use the MGWT CellList which works perfect.
I have the following problem. How can I keep selected cells selected such that the remain selected after the user releases the cell?
Here is my implementation:
CellList<Item> myCellList = new CellList<Item>(new ItemCell());
My ItemCell class:
public class ItemCell implements Cell<Item> {
private static Template TEMPLATE = GWT.create(Template.class);
public interface Template extends SafeHtmlTemplates {
#SafeHtmlTemplates.Template("<div>{0}</div>")
SafeHtml content(String cellContents);
}
#Override
public void render(SafeHtmlBuilder safeHtmlBuilder, Item model) {
SafeHtml content = TEMPLATE.content(model.getName());
safeHtmlBuilder.append(content);
}
#Override
public boolean canBeSelected(Item model) {
return true;
}
}
My Item class:
public class Item {
private String name;
public Item() {
setName("");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
What you want is selection handler. If you want single slection use SingleSelectionHandler, if you want multiple selections use MultiSelectionHandler,
Sample code :
SelectionModel<Item> selectionModel = new SingleSelectionModel<Item>();
cellList.setSelectionModel(selectionModel);
if you want to do anything on selection you can do it here
selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
public void onSelectionChange(SelectionChangeEvent event) {
/** Do your thing here **/
selectionModel.getSelectedObject(); //for single Selection
selectionModel.getSelectedSet(); //for multiple Selection
}
});
Related
I am making a program to iterate through an arraylist of objects and print them to the screen. To do this I am using a getName() method. When I call it from one of my classes, nothing is returned, but calling it from a different class works.
public class Customer {
String name;
public Customer(String name) {
this.name=name;
}
public String getName() {
return this.name;
}
}
The code above is the getName() method I want to call.
public class Store {
private String name;
private ArrayList<Customer> customersStore;
public Store(String name) {
this.name=name;
customersStore=new ArrayList<Customer>();
}
public void addCustomer(Customer customer) {
customersStore.add(customer);
for(int i = 0; i<customersStore.size();i++){
System.out.print(customersStore.get(i).getName() + " ");
}
}
public String getName() {
return this.name;
}
public ArrayList<Customer> getCustomers() {
return this.customersStore;
}
}
Because the program was not printing anything off as a way of debugging I had the program print off the arraylist whenever a new value was entered and found that it worked.
public class StoreView implements Observer{
public void printStoreDetails(Store store) {
ArrayList<Customer> customerList;
// Displaying the customer list
customerList = store.getCustomers();
// Displaying the values after iterating through the list
System.out.println("\nThe Customer names are:");
for(int i = 0; i<customerList.size();i++){
System.out.print(customerList.get(i).getName() + " ");
}
}
#Override
public void update(Observable o, Object name) {
printStoreDetails(new Store("Sears"));
}
}
However, when I try to call it from the StoreView class above, it does not print anything off. Which is what I dont understand.
The input is gathered from a scanner in the main class
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Store myStore = new Store("Sears");
StoreView myStoreView = new StoreView();
StoreController myStoreController = new StoreController(myStore, myStoreView);
Customer aCustomer;
System.out.println("Enter customer names for store " + myStore.getName());
myStoreController.addObserver(myStoreView);
while(input.hasNext()) {
aCustomer = new Customer(input.nextLine());
myStoreController.addCustomer(aCustomer);
}
}
}
The input is then sent to StoreController to be added to the ArrayList
public class StoreController extends Observable {
private Store model;
private StoreView view;
public StoreController(Store model, StoreView view){
this.model = model;
this.view = view;
}
public void addCustomer(Customer name){
model.addCustomer(name);
setChanged();
notifyObservers();
}
}
I'm not super familiar with observers but the overall goal of the program is to update StoreView whenever customers are added to the Store through StoreController. Any help is appreciated.
You are creating a new instance of Store when updating the observer; thus, it has an empty array of customers.
Change notifyObservers(); to notifyObservers(model); and the update method to:
#Override
public void update(Observable o, Object store) {
if (store instanceof Store) {
printStoreDetails((Store) store);
}
}
I have googled for a whole day but I just can't find an answer to my problem.
I'm using the MVC pattern.
Basically I have a list of songs (id, title, author, ect.) that I need to display in a JTable. The songs are stored in a MySQL database.The Connection to database works fine.
I'm currently storing all the reconds from my database in an 'ArrayList'
This is what I have so far:
The code to store the songs:
SongDAO songDAO = new SongDAO();
ArrayList<Song> songs = songDAO.findAll();
When printing out the songs, I get this output:
[oop.model.entities.Song#1055e4af, oop.model.entities.Song#3caeaf62, oop.model.entities.Song#e6ea0c6, oop.model.entities.Song#6a38e57f]
This is where I play the first song:
if (songs.isEmpty()) {
library = null;
} else {
library = songs.get(0);
Mainframe.setVisible(true);
firstController();
}
public static Library getLibrary() {
return library;
}
The library static factory method:
public static void firstController() {
new libraryController(view.libraryView);
}
I'm pretty sure the problem is here. I just can't figure it out for the life of me.
public class libraryController {
private libraryView view;
public libraryController(libraryView view) {
this.view = view;
for (Song song : baseController.getLibrary().getSongs()) {
view.addSong(song);
}
updateView();
}
public void updateView() {
view.setSongs(baseController.getLibrary().getSongs());
}
}
I've tried System.out.println(baseController.getLibrary().getSongs()), but all i get is [ ]. This leads me to believe the getSongs() method is the cause.
public void setSongs(ArrayList<Song> songs) {
for (Song song : songs) {
addSong(Song);
}
}
public void addSong(Song song) {
Object[] row = new Object[]{song.getId(), song.getTitle(), song.getArtist(), song.getAlbum(), song.getGenre(), song.getYear()};
model.addRow(row);
}
Here is my Library Class:
public class Library {
private ArrayList<Song> songs;
private int id;
private Song song;
public Library() {
id=0;
songs = new ArrayList<Song>(20);
}
public ArrayList<Song> getSongs() {
return songs;
}
public Libreria setSongs(ArrayList<Song> songs) {
this.songs = songs;
return this;
}
}
My song class:
public class Song extends Library {
private int id;
private String title;
private String artist;
private String album;
private String genre;
private int year;
private Library library;
public Song(){
id = 0;
}
public int getId() {return id; }
public void setId(int id) {this.id = id;}
public String getTitle() { return title;}
public void setTitle(String title) {this.title = title;}
public String getArtist() { return artist;}
public void setArtist(String artist) {this.artist = artist;}
public String getAlbum() {return album;}
public void setAlbum(String album) {this.album = album; }
public String getGenre() {return genre;}
public void setGenre(String genre) {this.genre = genre;}
public int getYear() {return year;}
public void setYear(int year) {this.year = year;}
public Library getLibrary() {return library;}
public Song setLibrary(Library library) {
this.library = library;
return this;
}
}
If anyone could help me, that would be greatly appreciated.
Basically i have to display in JTable my songs ('id','title,'author','..')
Swing components are already designed using a modified version of MVC.
If you want to display data in a JTable you just need to load the data into a TableModel.
So you may want to create a custom TableModel so hold your Song objects.
Check out Table Row Model.
It shows you step by step how to create a custom model for the Song object. Or if you want you can use the generic TableRowModel to make the coding easier.
Once you create the SongTableModel the code to use it would be something like:
SongTableModel model = new SongTableModel( songs );
JTable table = new JTable( model );
What is the proper relationship, in code, between a table model and the actual database queries?
Inside the addRow() method in the table model, should I place a further call to my database class, which in turn inserts the row into the database? I've illustrated this in the below code snippets.
public class MainPanel extends JPanel
{
...
public MainPanel()
{
personTableModel = new PersonTableModel();
personTable = new JTable(personTableModel);
...
insertButton = new JButton("Insert");
insertButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
String name = nameTextBox.getText();
String address = addressTextBox.getText();
Object[] row = { name, address };
personTableModel.addRow(row); // <--- Add row to model
}
});
}
}
public class PersonTableModel extends AbstractTableModel
{
private List<Object[]> data;
private List<String> columnNames;
PersonDB personDB = new PersonDB();
...
public void addRow(Object[] row)
{
// insert row into 'data'
personDB.addPerson(row); // <---- Call the personDB database class
}
...
}
public class PersonDB
{
public PersonDB()
{
// establish database connection
}
public addPerson(Object[] row)
{
// code that creates a SQL statement based on row data
// and inserts new row into database.
}
...
}
Whether or not you should directly make an insert call depends on some aspects:
Do you want other processes to access the data immediately?
Do you fear that your program crashes and you lose important information?
Can you ensure that any data persisted during addRow is meaningful (the program could terminate directly after the insert)?
Than of course it may be a good idea to directly insert the data into the backing Database.
You should however watch out, that there are two variants of addRow and two variants of insertRow. DefaultTableModel directs calls internally through insertRow(int, Vector), which would probably be the only function to overwrite, if you want to immediately persist data.
If you like the proposed idea of DTOs the examples below may help you.
The Idea is to represent "Entities" or table rows as classes in Java. A DTO is the simplest representation and normally only contains fields with respective getter and setter.
Entities can generically be persisted and loaded through ORM libraries like EclipseLink or Hibernate. Additionally for this table-application the use of DTOs provide a way of storing data not shown to the user in a clean and typed way.
DTO:
public class PersonDto {
private Long id;
private String name;
private String street;
public PersonDto() {
}
public PersonDto(Long id, String name, String street) {
this.id = id;
this.name = name;
this.street = street;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public static class NameColumn extends DtoTableModel.ColumnProvider<PersonDto, String> {
public NameColumn() {
super("Name", String.class);
}
#Override
public String getValue(PersonDto dto) {
return dto.getName();
}
#Override
public void setValue(PersonDto dto, Object value) {
dto.setName((String) value);
}
}
public static class StreetColumn extends DtoTableModel.ColumnProvider<PersonDto, String> {
public StreetColumn() {
super("Street", String.class);
}
#Override
public String getValue(PersonDto dto) {
return dto.getStreet();
}
#Override
public void setValue(PersonDto dto, Object value) {
dto.setStreet((String) value);
}
}
}
DTO based TableModel:
import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
public class DtoTableModel<T> extends AbstractTableModel {
private final ArrayList<T> rows;
private final ArrayList<ColumnProvider<T, ?>> columns;
protected DtoTableModel() {
rows = new ArrayList<T>();
columns = new ArrayList<ColumnProvider<T, ?>>();
}
#Override
public int getRowCount() {
return rows.size();
}
#Override
public int getColumnCount() {
return columns.size();
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return columns.get(columnIndex).getValue(rows.get(rowIndex));
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
final ColumnProvider<T, ?> column = columns.get(columnIndex);
column.setValue(rows.get(rowIndex), aValue);
this.fireTableCellUpdated(rowIndex, columnIndex);
}
#Override
public String getColumnName(int column) {
return columns.get(column).getTitle();
}
public void addColumn(ColumnProvider<T, ?> column) {
this.columns.add(column);
this.fireTableStructureChanged();
}
public void addRow(T row) {
this.rows.add(row);
this.fireTableRowsInserted(this.rows.size() - 1, this.rows.size() - 1);
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return this.columns.get(columnIndex).getValueClass();
}
public static abstract class ColumnProvider<T, V> {
private String title;
private final Class<V> valueClass;
protected ColumnProvider(String title, Class<V> valueClass) {
this.title = title;
this.valueClass = valueClass;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Class<V> getValueClass() {
return valueClass;
}
public abstract V getValue(T dto);
public abstract void setValue(T dto, Object value);
}
}
Example-"Application":
import javax.swing.*;
import java.awt.*;
public class JTableTest extends JFrame {
private final JTable jTable;
public JTableTest() throws HeadlessException {
super("JFrame test");
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
final GridBagLayout layout = new GridBagLayout();
final Container contentPane = this.getContentPane();
contentPane.setLayout(layout);
final GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
final DtoTableModel<PersonDto> dm = new DtoTableModel<PersonDto>();
jTable = new JTable(dm);
dm.addColumn(new PersonDto.NameColumn());
dm.addColumn(new PersonDto.StreetColumn());
dm.addRow(new PersonDto(1L, "Paul", "Mayfairy Street"));
dm.addRow(new PersonDto(2L, "Peter", "Ferdinand Street"));
JScrollPane scrollpane = new JScrollPane(jTable);
contentPane.add(scrollpane, gridBagConstraints);
this.pack();
}
public static void main(String[] args) {
final JTableTest jTableTest = new JTableTest();
jTableTest.setVisible(true);
}
}
I have custom class that implements Parcelable and I use it as custom arraylist.
When I use putParcelableArrayListExtra and 400 rows it works fine, but 1000 rows it does not. I have black screen and app locks up. What is wrong?
EDIT:
I sent it here and I don't use it in another Activity.
Intent intent = new Intent().setClass(getApplicationContext(), ArtActivity.class);
intent.putParcelableArrayListExtra ("mylist", list);
startActivityForResult(intent, SECONDARY_ACTIVITY_REQUEST_CODE);
My array:
ArrayList<Piece> list = new ArrayList<Piece>();
It is my Class:
public class Piece implements Parcelable {
private String id;
private String name;
private int type;
private String text;
private String mp3;
public Piece (String id,String name,int type)
{
this.id=id;
this.name=name;
this.type=type;
}
public Piece(Piece ele)
{
this.id=ele.id;
this.name=ele.name;
this.type=ele.type;
this.text=ele.text;
}
public Piece (Parcel in)
{
id = in.readString ();
name = in.readString ();
type = in.readInt();
text= in.readString();
mp3=in.readString();
}
public static final Parcelable.Creator<Piece> CREATOR
= new Parcelable.Creator<Piece>()
{
public Piece createFromParcel(Parcel in)
{
return new Piece(in);
}
public Piece[] newArray (int size)
{
return new Piece[size];
}
};
public void makeText(String text)
{
this.text=text;
}
public void makeMp3(String mp3)
{
this.mp3= mp3;
}
public String getMp3()
{
return this.mp3;
}
public String getId()
{
return id;
}
public String getName()
{
return name;
}
public int getType()
{
return type;
}
public String getText()
{
return text;
}
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeString (id);
dest.writeString (name);
dest.writeInt(type);
dest.writeString (text);
dest.writeString (mp3);
}
}
I do not believe you should be using parcelable in this case. I would either access the data statically (if you only intend to have one persistent instance of the data), or use a caching system to hold onto the data.
This is an example of a publicly available static variable:
public static List<Piece> list;
It is accessible from everywhere in your app that has visibility of the class.
However, doing this is very messy and is considered a bad practice. Alternatively, you can create an object to manage the data for you as a static class or singleton:
public class MyListManager {
private static List<Piece> mList;
public static List<Piece> getMyList() {
return mList;
}
public static void setList(List<Piece> list) {
mList = list;
}
}
Alternatively, you can implement some kind of a caching system to manage your data.
I have a question about the handling of node properties in an outlineview.
I have three level of nodes, the rootNode, the node and each node may have sub-nodes. Apart from the rootNode, all nodes and subnodes shall have the same (Boolean => checkbox) property. In my outlineview I have two columns, the node(s) column, and a property column with checkboxes.
What I need now is the behaviour, that when I activate the checkbox of a node, all its sub-nodes checkboxes shall be activated as well, when I deactivate the checkbox of a node, all its sub-nodes checkboxes shall be de-activated as well. If I expand the tree to see the sub-nodes, each sub-node may be selected as well.
My current code looks like the following (some parts are found on the internet):
The main api
public class Category {
private String name;
private Boolean x;
public Category() {
this("empty");
}
public Category(String name) {
this.name = name;
}
public Category(String name, Boolean x) {
this.name = name;
this.x = x;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean getx() {
return x;
}
public void setx(Boolean x) {
this.x = x;
}
}
My ChildFactory for the nodes (category) looks like
public class CategoryChildrenFactory extends ChildFactory.Detachable<Category> {
/* detachable has no real effect on the current code, used to control
the life cylce */
#Override
protected boolean createKeys(List<Category> toPopulate) {
toPopulate.add(new Category("Cat1", false));
toPopulate.add(new Category("Cat2", false));
toPopulate.add(new Category("Cat3", false));
return true;
}
#Override
protected Node createNodeForKey(Category key) {
AllNode cn = new AllNode(key);
return cn;
}
}
and for the sub-nodes
public class MovieChildrenFactory extends ChildFactory<String>{
Category category;
public MovieChildrenFactory(Category category) {
this.category = category;
}
#Override
protected boolean createKeys(List<String> toPopulate) {
toPopulate.add("m_1");
toPopulate.add("m_2");
toPopulate.add("m_3");
return true;
}
#Override
protected Node createNodeForKey(String key) {
return new AllNode(category, key);
}
}
The nodes creation is put into a single class for both types (nodes, subnodes)
public class AllNode extends AbstractNode {
Category category;
String title;
private Sheet.Set set;
public AllNode(Category category) {
this(category, null);
this.category = category;
set = Sheet.createPropertiesSet();
}
public AllNode(Category category, String title) {
super(Children.LEAF, Lookups.singleton(category));
if (title == null) {
this.setChildren(Children.create(new MovieChildrenFactory(category), true));
}
this.title = title;
set = Sheet.createPropertiesSet();
}
#Override
public String getHtmlDisplayName() {
String name = "";
if (title == null) {
name = category.getName();
} else {
name = title;
}
return name;
}
#Override
protected Sheet createSheet() {
Sheet sheet = Sheet.createDefault();
Category obj = getLookup().lookup(Category.class);
PlotMathProperties pmp = new PlotMathProperties(obj, title);
set.put(pmp.getMyProperty());
sheet.put(set);
return sheet;
}
}
The properties are handled by
public class PlotMathProperties {
private MyProperty myProperty;
private String categoryName;
private String title;
public PlotMathProperties(Category category, String title) {
this.categoryName = category.getName();
this.title= title;
this.myProperty= new MyProperty ();
}
public XProperty getMyProperty () {
return myProperty;
}
public class MyProperty extends PropertySupport.ReadWrite<Boolean> {
private Boolean isMyProp = false;
public MyProperty () {
super("x", Boolean.class, "XPROP", "Is this a coloured or black and white movie");
}
#Override
public Boolean getValue() throws IllegalAccessException, InvocationTargetException {
return isMyProp ;
}
#Override
public void setValue(Boolean val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
isMyProp = val;
if (isMyProp) {
System.out.println("active: " + categoryName + ", " + title);
} else {
System.out.println("de-active: " + categoryName + ", " + title);
}
}
}
}
Together with a TopComponent the outlineview looks nice and works well.
Has anyone an idea how to setup the the behaviour for the check-boxes
regards