JLists with a set of objects - java

i am making a twitter client (desktop application) in Java, i am using twitter4j API also. i have managed to do the search for tweets and i get back results and i show them in a Jlist.
what i want is that i want to show tweets nicely in the list, not only as a text .. show the image of the user, the tweet, tweeted by ... etc all this information .. in addition attach additional data like star rating .. how can i add that to a JList ? can the Jlist hold different objects .. Jpanels for example ..

Instead I suggest you put a set of JPanels inside a JScrollPane.

A JList's renderer must be a JComponent, so you can use any Swing object, including JPanels.
You can also use HTML in a JLabel if it is easier to do so than using a JPanel.
To use a custom renderer, you do something like this..
myList.setCellRenderer(new CustomRenderer());
and then create a renderer like this
public class CustomRenderer extends DefaultListCellRenderer {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean hasFocus) {
JPanel panel = new JPanel();
// set up the panel for your exact display requirements.
return(panel);
}
}

Suggest using a JTable, which has several columns, instead of a JList.
Also suggest using GlazedLists, which makes it really easy to display lists with fields in a JTable, so that they update automatically when the underlying list changes.
Here's an example of some code I wrote recently which displays something similar:
private void bindEmailTargetTable(NotificationModel newModel) {
JTable table = getUI(UIKey.EMAIL_TARGET_TABLE);
EventList<EmailTarget> displayList = newModel.getEmailTargets();
TableFormat<EmailTarget> tf = new TableFormat<EmailTarget>()
{
#Override public int getColumnCount() {
return 4;
}
private final String[] columns = { "address", "description", "msg left", "msg limit" };
#Override public String getColumnName(int col) {
return this.columns[col];
}
#Override public Object getColumnValue(EmailTarget item, int col) {
switch (col)
{
case 0:
return item.getAddress();
case 1:
return item.getDescription();
case 2:
return item.getRemainingMessages();
case 3:
return item.getMessageLimit();
default:
return "";
}
}
};
EventTableModel<EmailTarget> etm = new EventTableModel<EmailTarget>(displayList, tf);
table.setModel(etm);
}
That's 33 lines of code to take a JTable and make it automatically update itself to display 4 fields of each EmailTarget in an EventList<EmailTarget>.
For non-text field contents, you just need a custom TableCellRenderer.

AS Jason suggested its better to go for jtable instead of JLIst. In fact you can use any free Java based table classes that have extended functionality over JTables. JIDE is one such library but its commercial. you can search and find a lot..

Related

Add a JButton to a JTable cell

I have a JTable with a model created like this :
DefaultTableModel model = new DefaultTableModel(new Object[][] {},new String[] {"Col1", "Col2", "Col3", "Col4", "Col5", "Col6", "Col7", "Col8"}) {
#Override
public Class<?> getColumnClass(int column) {
switch (column) {
case 0: return ImageIcon.class;
case 7: return JButton.class;
default: return String.class;
}
}
};
table = new JTable(model);
But when I use the addRow method, My ImageIcon appears properly but not the JButton. In fact, I get something like javax.Swing.JButt... instead of the JButton!
When you are adding a new row, it is being populated correctly. (You can see the ImageIcon).
So, the JButton object is also being inserted correctly.
The only difference here, JTable does not know how to display it or handle events on it.
That is why JTable calls toString() method on JButton and displays the text (as you mentioned).
javax.swing.JButt......
To overcome this problem, we need to supply two additional objects to the JTable.
TableCellEditor to handle events.
TableCellRenderer to handle painting.
You can find additional information about implementation details here : How to use custom JTable cell editor and cell renderer
Hope this helps.
Good luck.
Edit in response to the comment.
table.getColumnModel().getColumn(7).setCellRenderer(new MyCellRenderer());
// Put painting logic in MyCellRenderer class.
This way you can assign different renderer objects to different columns.
The problem is that JTable doesn’t support a button renderer or editor. You can overcome it using a custom cell editor, ButtonColumn : http://tips4java.wordpress.com/2009/07/12/table-button-column/

Java - Updating JTable with fireTableDataChanged();

I have a JTable in my program. I want to update it after clicking JButton.
I wrote this:
DefaultTableModel myTable = new DefaultTableModel(celDatas,celNames);
JTable source = new JTable(myTable){public boolean isCellEditable(int rowIndex, int colIndex) {
return false;}};
JScrollPane pane = new JScrollPane(source);
(...)
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
query = "Select sal FROM EMP";
myTable =(DefaultTableModel)source.getModel();
myTable.fireTableDataChanged();
}
The problem is that id doesn't update my data on JTable.
How to resolve this problem?
EDIT:
JTable is displayed in my guy through JScrollPane.
I make now this:
source = new JTable(myTable){public boolean isCellEditable(int rowIndex, int colIndex) {return false;}};
pane = new JScrollPane(source);
I made also a new void, where is getting datas from database + there I define myTable:
void queryConnection() {
(...)
myTable = new DefaultTableModel(celDatas,celNames);
}
I added a JButton, which update my JTable (when we change the query.
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
query = "Select sal FROM EMP";
queryConnection();
}
}
================================================================================
public class Application2 implements Runnable {
private JTable source;
private JScrollPane pane;
private DefaultTableModel myTable;
private JPanel panel;
private String[][] celDatas = null;
private String[] celNames = null;
public void run() {
(...)
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
if(...) {
query = "Select sal FROM EMP";
queryConnection();
}
}
if(query == null) {
query = "Select * from EMP";
queryConnection();
}
source = new JTable(myTable){public boolean isCellEditable(int rowIndex, int colIndex) {return false;}};
pane = new JScrollPane(source);
pane.setSize(f.getSize().width-60,300);
pane.setLocation(30,20);
panel.add(pane);
f.add(panel);
f.pack();
}
void queryConnection() {
//here is connection and downloading datas
myTable = new DefaultTableModel(celDatas,celNames);
}
I hope that it is right now more convenient? ;)
You don't need to call any fireXXX() methods if you're creating a new TableModel, but rather you mainly need to call these if you're writing your TableModel based on AbstractTableModel (you're not).
Your problem lies elsewhere I think. You seem to be creating a new JTable and adding it to a new JScrollPane. Are you adding these components to your GUI (you don't show)? If so, is the container that you're adding to able to accept new components smoothly? Do you revalidate and repaint the container? Is your newly created JTable being displayed in the GUI?
Or, is there a JTable already displayed in your GUI? If so, perhaps all you want to do is set its model rather create a new JTable. I favor this solution as the easiest.
Edit 1
I would do something like so:
Access Database in a background thread and get information from it.
Create a new DefaultTableModel object filling it with data extracted from the database.
I would not create a new JTable if one already exists. Instead I'd simply call setTableModel(...) on the currently displayed JTable and pass in my newly created DefaultTableModel object.
Then I'd sit back and enjoy the big bucks and other fruits of my success.
Edit 2
Ganjira, for us to be able to best help you, we need to understand the problem better, which is why I've requested either full clarification of your problem or an sscce, of which I've seen neither. My problems with understanding your issues include:
Again, do you have a JTable already displayed in your GUI, and now you're trying to change the data that is displayed in the JTable based on data extracted from a database?
If so, why not simply change the model of the existing JTable rather than create a whole new JTable?
If you don't already have a JTable in the application and now you want to display one, you state that your data is not being displayed but don't show code to help us understand why.
If you can answer the first two questions, we may not need an sscce, but if not, please understand that your current post is no where close to being an sscce, in that we cannot run it, we cannot compile it, it doesn't reproduce your problem for us,... I have to wonder if you've even read the link yet as it explains why all of these conditions are important (that and brevity so as not to drown us in a large amount of unrelated code).
No, it is not required that you post an SSCCE, but if we can't help you based on the text in your question and your code snippets, it does offer a better chance of allowing us to understand the problem and find a solution for you.
Edit 3
You state:
JTable's been already in GUI, because it shows the 'beginning of the program'. After clicking JButton I want to change values in JTable. It doesn't change the model of the existing JTable - it doesn't change nothing.
And this confuses me as the best solution is one I've been suggesting all along -- Don't make a new JTable, but instead create a new DefaultTableModel and change the model for the existing JTable. You've yet to mention why you're not trying this, or if you have tried it, how it's not working for you.

SwingX JXTable: use ColorHighlighter to color rows based on a "row object"

I'm using JXTable and I know how to do this based on DefaultRenderers for JTable, but I want to know how to do it in a way that's JXTable-friendly based on HighlighterPipeline.
I have a list of objects displayed in a table, and each row represents one object. I would like to color the rows displaying objects of a certain type a different color.
It looks like I should be using ColorHighlighter. But I can't find examples for this, other than the simple highlighters like "color every other row" or some such thing.
I need the row number since there's no such thing as a "row object" in the JTable/TableModel paradigm, but if I can do that, I can easily test a predicate and return true/false to tell the highlighter to kick in or not.
Can someone help me figure out the right direction to get this to work?
never mind, I figured it out. It was just hard to figure out the way to use ComponentAdapter propertly.
JXTable table = ...
final List<Item> itemList = ...
final HighlightPredicate myPredicate = new HighlightPredicate() {
#Override
public boolean isHighlighted(
Component renderer,
ComponentAdapter adapter) {
Item item = itemList.get(adapter.row);
return testItem(item);
}
public boolean testItem(Item item) { ... }
}
ColorHighlighter highlighter = new ColorHighlighter(
myPredicate,
Color.RED, // background color
null); // no change in foreground color
table.addHighlighter(highlighter);

Java swing UI implementation, most likely involving a PropertyChangeListener

My use case is as follows --
I have a list(ArrayList) of objects, custom data objects.
Now i want to display or represent each of these data objects as a Box containing 3 buttons. So i would have n Boxes for n given data objects in my list.
I want each of these 'boxes' to be stacked in a , say, JTable.
Now, whenever a data object is added to the aforementioned list, i want another Box to be created as mentioned before and added to the JTable.
I know this can be accomplished using PropertyChangeListener but i went through some articles online regarding PropertyChangeListener but was not able to get a clear implementable idea.
im new to building UIs and any help with this would be much appreciated.
I would recommend wrapping your ArrayList within a TableModel implementation, whereby modifications to the list will fire a TableModelEvent.
In the example below the underlying List is encapsulated within the model implementation; the only way to modify it is by calling addItem, which will call fireTableRowsInserted after modifying the list. This will result in a TableModelEvent being fired and subsequently processed by the JTable view onto this model instance.
public class MyTableModel extends AbstractTableModel {
private final List<MyItem> items = new ArrayList<MyItem>();
public int getRowCount() {
return items.size();
}
public int getColumnCount() {
return 3;
}
public String getColumnName(int columnIndex) {
switch(columnIndex) {
case 0:
return "foo";
case 1:
return "bar";
case 2:
return "qux";
default:
assert false : "Invalid column index: " + columnIndex;
}
}
public void addItem(MyItem item) {
items.add(item);
fireTableRowsInserted(items.size() - 1, items.size() - 1);
}
}

ListCellRenderer not Firing Events on Child Components

The following ListCellRenderer does not receive click events on the nested ComboBoxes. Do I need to enable something?
class FilterCellRenderer implements ListCellRenderer {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Filter filter = (Filter)value;
JPanel filterPanel = new JPanel();
FlowLayout layout = new FlowLayout();
layout.setAlignment(FlowLayout.LEFT);
filterPanel.setLayout(layout);
filterPanel.add(new JLabel(filter.getLabel()));
final List<Object> options = filter.getOptions();
if (options.size() > 1) {
JComboBox optionCombo = new JComboBox(new AbstractComboBoxModel() {
public int getSize() {
return options.size();
}
public Object getElementAt(int index) {
return options.get(index);
}
});
optionCombo.setSelectedItem(filter.getValue());
filterPanel.add(optionCombo);
}
if (isSelected) {
filterPanel.setBackground(list.getSelectionBackground());
filterPanel.setForeground(list.getSelectionForeground());
}
return filterPanel;
}
}
Renderer components in swing work like "rubber stamps" -they are just used to render/paint a value and are not added to the parent container in the usual way (just think how a single component could be added in multiple places!).
It sounds like you may want an editor rather than a renderer (an editor is a fully-fledged component, added in one place at any given time). Failing that you will have to install the MouseListener on the JList instead.
Since I didn't need to select rows, I ended up just dynamically adding and elements to a JPanel with a custom layout. Allowed for full component behaviour without having to hack a table.
It's a little bit tricky this. I believe you need to replace the JList with a single column JTable. Then set a table cell editor as well as renderer. IIRC, there might be a problem losing the first click (which gets used to select that cell edited).
Also it's a very good idea to reuse the components between each call to getCellRendererComponent. The components are used as a stamp and then discarded. Performance will suck massively if they are recreated each time.

Categories

Resources