If I update a JList with a long number of html formatted items then the controls stop responding and indicators won't update. This makes sense, the event thread is busy. The title can still be set though. Why is this?
Here's some (long) code demonstrating this:
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.*;
public class JListTest extends JFrame {
class TestListModel extends AbstractListModel<String> {
private static final long serialVersionUID = JListTest.serialVersionUID;
private boolean useHtml;
private String[] formattedList = new String[] {};
public int getSize() {
return formattedList.length;
}
public String getElementAt(int index) {
return formattedList[index];
}
public void setUseHtml(boolean useHtml) {
this.useHtml = useHtml;
}
public String getNewListItem() {
if (useHtml) {
return "<html><div style='padding:2px"
+ ";background-color:#EDF5F4;color:black'><div style='padding:2px;font-weight:500;'>"
+ "Item " + (100 * Math.random())
+ "</div>"
+ "This will change!"
+ "</div></html>";
} else {
return "Item " + (100 * Math.random());
}
}
public void updateItems() {
formattedList = new String[] {"<html><h1>Loading!</h1></html>"};
fireContentsChanged(this, 0, 1);
Thread buildItems = new Thread() {
#Override
public void run() {
final String[] tempList = new String[3000];
for (int i=0; i<tempList.length; i++) {
tempList[i] = getNewListItem();
}
// Just show the string bashing's done
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
formattedList = new String[] {"<html><h1>Updating!</h1></html>"};
fireContentsChanged(TestListModel.this, 0, 1);
}
});
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Update
SwingUtilities.invokeLater(new Runnable() {
public void run() {
formattedList = tempList;
fireContentsChanged(TestListModel.this, 0, formattedList.length);
}
});
}
};
buildItems.start();
}
}
protected static final long serialVersionUID = 1L;
public JListTest() {
JPanel controlPanel = new JPanel();
JButton updaterControl = new JButton("Add 3000");
final JCheckBox useHtmlControl = new JCheckBox("Use HTML");
final TestListModel model = new TestListModel();
JList<String> list = new JList<String>(model);
JScrollPane scrollPane = new JScrollPane(list);
final JLabel durationIndicator = new JLabel("0");
controlPanel.add(useHtmlControl, BorderLayout.WEST);
controlPanel.add(updaterControl, BorderLayout.EAST);
getContentPane().add(controlPanel, BorderLayout.PAGE_START);
getContentPane().add(scrollPane, BorderLayout.CENTER);
getContentPane().add(durationIndicator, BorderLayout.PAGE_END);
useHtmlControl.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.setUseHtml(useHtmlControl.isSelected());
}
});
useHtmlControl.setSelected(false);
updaterControl.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.updateItems();
}
});
Timer counter = new Timer();
counter.schedule(new TimerTask() {
#Override
public void run() {
String previousCounter = durationIndicator.getText();
String newCounter = Integer.toString(
Integer.parseInt(previousCounter) + 1);
durationIndicator.setText(newCounter);
setTitle(newCounter);
}
}, 0, 100);
}
public static void main(String args[]) {
JListTest jlt = new JListTest();
jlt.pack();
jlt.setSize(300, 300);
jlt.setVisible( true );
}
}
The answer is pretty obvious - because Window title is not a Swing component, it's OS native entity.
So changes don't have to go through Swing Event Queue, but go to XDecoratedPeer.updateWMName directly in case of Unix and to some other class in other OSes.
The more interesting question would be how to avoid that UI blocking, but I don't think that's possible with just Swing, you'll have to implement some lazy loading, or rendering in batches.
Related
How do I get the text of two JLabels when copying JLabel's text with TransferHandler?
Label1111111 How can I keep the text of both JLabels when copied to Label2222222.
For this reason, I will take control of two Jlabel's texts. This shape can only get the text of JLabel, which was first held. Thank you in advance for your help.
public class deneme2 extends JFrame {
private static final int COPY = 0;
private static final int NONE = 0;
private JPanel contentPane;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
deneme2 frame = new deneme2();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public deneme2() {
JPanel panel= new JPanel();
MouseListener listener = new DragMouseAdapter();
JLabel label1 = new JLabel("Label1111111", JLabel.CENTER);
handlerLabel(label1);
label1.addMouseListener(listener);
panel.add(label1);
JLabel label2 = new JLabel("Label2222222", JLabel.CENTER);
handlerLabel(label2);
label2.addMouseListener(listener);
panel.add(label2);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
contentPane.add(panel);
setContentPane(contentPane);
}
private void handlerLabel (JLabel lbl)
{
lbl.setTransferHandler(new TransferHandler("text") {
#Override
protected void exportDone(JComponent source, Transferable data, int action) {
if (action == COPY){
((JLabel)lbl.getDropTarget().getDropTargetContext().getComponent()).getText();
//((JLabel) source).setText("LabelEmpty");
}
}
});
}
private class DragMouseAdapter extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
JComponent comp = (JComponent)e.getSource();
TransferHandler handler = comp.getTransferHandler();
handler.exportAsDrag(comp, e, TransferHandler.COPY);
}
}
}
Maybe in this way. I added inner class MyLabel and console output in your handlerLabel. Ctrl+v this under your main. It will print to console the original String property of each MyLabels.
public class MyLabel extends JLabel {
String original;
public MyLabel (String text)
{
super(text);
this.original=text;
}
public String getOriginal() {
return original;
}
public void setOriginal(String original) {
this.original = original;
}
}
public deneme2() {
JPanel panel= new JPanel();
MouseListener listener = (MouseListener) new DragMouseAdapter();
MyLabel label1 = new MyLabel("Label1111111");
handlerLabel(label1);
label1.addMouseListener(listener);
panel.add(label1);
MyLabel label2 = new MyLabel("Label2222222");
handlerLabel(label2);
label2.addMouseListener(listener);
panel.add(label2);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
contentPane.add(panel);
setContentPane(contentPane);
}
private void handlerLabel(MyLabel lbl) {
lbl.setTransferHandler(new TransferHandler("text") {
#Override
protected void exportDone(JComponent source, Transferable data, int action) {
if (action == COPY) {
System.out.println(((MyLabel) lbl.getDropTarget().getDropTargetContext().getComponent()).getOriginal());
}
}
});
}
Edit: check this out. Ctrl+V this under your main. It will print to console text of source label and text of target label, also the original property. Class MyLabel implements DropTargetListener , which is then registered by new DropTarget(this, this). Then we define what will happen in overriden drop method.
public class MyLabel extends JLabel implements DropTargetListener {
String original;
public MyLabel(String text) {
super(text);
this.original = text;
new DropTarget(this, this);
this.setTransferHandler(new TransferHandler("text"));
final MouseListener listener = new MouseAdapter() {
#Override
public void mousePressed(final MouseEvent me) {
final MyLabel label = (MyLabel) me.getSource();
final TransferHandler handler = label.getTransferHandler();
handler.exportAsDrag(label, me, TransferHandler.COPY);
}
};
this.addMouseListener(listener);
}
public String getOriginal() {
return original;
}
public void setOriginal(String original) {
this.original = original;
}
#Override
public void dragEnter(DropTargetDragEvent dtde) {
}
#Override
public void dragOver(DropTargetDragEvent dtde) {
}
#Override
public void dropActionChanged(DropTargetDragEvent dtde) {
}
#Override
public void dragExit(DropTargetEvent dte) {
}
#Override
public void drop(DropTargetDropEvent dtde) {
try {
final String sourceString = (String) dtde.getTransferable().getTransferData(new DataFlavor("application/x-java-jvm-local-objectref; class=java.lang.String"));
System.out.println("Source: " + sourceString + " target: " + this.getText());
this.setText(sourceString);
System.out.println("Original target: "+this.getOriginal());
} catch (final UnsupportedFlavorException | IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public deneme2() {
JPanel panel = new JPanel();
MyLabel label1 = new MyLabel("Label1111111a");
panel.add(label1);
MyLabel label2 = new MyLabel("Label2222222b");
panel.add(label2);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
contentPane.add(panel);
setContentPane(contentPane);
}
}
EDIT2: Following code generates this result see result at the end of this answer:
or
It also prints original property to console. Those could be organised differently (MyLabel, MyLabelTransferable, MyLabelDropTargetListener, MyLabelTransferHandler classes, just to give an idea for future refactoring) but it works in this way too. Consider it a quickfix for your use case.
So main class is this:
public class Deneme2 extends JFrame {
private static final int COPY = 0;
private static final int NONE = 0;
public static void main(String[] args) {
Deneme2 mainFrame = new Deneme2();
SwingUtilities.invokeLater(() -> {//let's get that frame on EDT rollin lambda style:)
mainFrame.setVisible(true);
});
}
public Deneme2() {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
MyLabel label1 = new MyLabel("Label1111111a");
panel.add(label1, BorderLayout.WEST);
MyLabel label2 = new MyLabel("Label2222222b");
panel.add(label2, BorderLayout.EAST);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setBounds(100, 100, 450, 300);
panel.setBorder(new EmptyBorder(5, 5, 5, 5));
this.add(panel);
}
}
Then MyLabel.java :
public class MyLabel extends JLabel implements DropTargetListener, Transferable {
String original;
protected static final DataFlavor MYLABEL_DATA_FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + "; class=\"" + MyLabel.class.getCanonicalName() + "\"",
"MyLabel label");
protected static final DataFlavor[] SUPPORTED_FLAVORS = {MYLABEL_DATA_FLAVOR};
public MyLabel(String text) {
super(text);
this.original = text;
new DropTarget(this, this);
this.setTransferHandler(new MyLabelTransferHandler()); //here we use our custom TransferHandler
final MouseListener listener = new MouseAdapter() {
#Override
public void mousePressed(final MouseEvent me) {
final MyLabel label = (MyLabel) me.getSource();
final TransferHandler handler = label.getTransferHandler();
handler.exportAsDrag(label, me, TransferHandler.COPY);
}
};
this.addMouseListener(listener);
}
public String getOriginal() {
return original;
}
public void setOriginal(String original) {
this.original = original;
}
#Override
public void dragEnter(DropTargetDragEvent dtde) {
if (dtde.getTransferable().isDataFlavorSupported(MyLabel.MYLABEL_DATA_FLAVOR)) {
System.out.println("Drop accept - MyLabel");
dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
} else {
dtde.rejectDrag();
}
}
#Override
public void dragOver(DropTargetDragEvent dtde) {
//System.out.println("Drag over");
}
#Override
public void dropActionChanged(DropTargetDragEvent dtde) {
System.out.println("Action changed");
}
#Override
public void dragExit(DropTargetEvent dte) {
System.out.println("Exited");
}
#Override
public void drop(DropTargetDropEvent dtde) {
System.out.println("Drop detected");
if (dtde.getTransferable().isDataFlavorSupported(MyLabel.MYLABEL_DATA_FLAVOR)) {
Transferable t = dtde.getTransferable();
if (t.isDataFlavorSupported(MyLabel.MYLABEL_DATA_FLAVOR)) {
try {
Object transferData = t.getTransferData(MyLabel.MYLABEL_DATA_FLAVOR);
if (transferData instanceof MyLabel) {
MyLabel mySourceLabel = (MyLabel) transferData;
if (!(mySourceLabel.equals(this))) {
dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
this.setText(mySourceLabel.getText());
mySourceLabel.setText("Empty");
System.out.println(mySourceLabel.getOriginal() + " " + this.getOriginal());
} else {
dtde.rejectDrop();
System.out.println("Drop rejected - the same MyLabel");
}
} else {
dtde.rejectDrop();
}
} catch (UnsupportedFlavorException | IOException ex) {
dtde.rejectDrop();
}
} else {
dtde.rejectDrop();
}
}
}
#Override
public DataFlavor[] getTransferDataFlavors() {
return SUPPORTED_FLAVORS;
}
#Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor.equals(MYLABEL_DATA_FLAVOR) || flavor.equals(DataFlavor.stringFlavor);
}
#Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if (flavor.equals(MYLABEL_DATA_FLAVOR)) {
return this;
} else if (flavor.equals(DataFlavor.stringFlavor)) {
return this.getText();
} else {
throw new UnsupportedFlavorException(flavor);
}
}
}
And then MyLabelTransferHandler.java :
public class MyLabelTransferHandler extends TransferHandler {
#Override
public boolean canImport(TransferHandler.TransferSupport support) {
return (support.getComponent() instanceof MyLabel) && support.isDataFlavorSupported(MyLabel.MYLABEL_DATA_FLAVOR);
}
#Override
public boolean importData(JComponent src, Transferable transferable) {
return src instanceof MyLabel;
}
#Override
public int getSourceActions(JComponent c) {
return DnDConstants.ACTION_COPY;
}
#Override
protected Transferable createTransferable(JComponent c) {
Transferable t = (MyLabel)c;
return t;
}
#Override
protected void exportDone(JComponent source, Transferable data, int action) {
System.out.println("Export done.");
}
}
After final edit result looks like this:
Little clarification:
protected static final DataFlavor MYLABEL_DATA_FLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + "; class=\"" + MyLabel.class.getCanonicalName() + "\"",
"MyLabel label");
in MyLabel. That's important line. This will make getTransferData() return the same instance of MyLabel. If you would do it like:
protected static final DataFlavor MYLABEL_DATA_FLAVOR = new DataFlavor(MyLabel.class, "MyLabel label");
you won't be able to change mySourceLabel text to "Empty" in overridden drop() method, since you would be given a copy of that object.
Also Why shouldn't you extend JFrame and other components? . And you can provide checking for "Empty" text (if getText() returns "Empty", then don't change text in target MyLabel).
Found a neat sample that really helped with illustrating how DnD works when it drags a values from a list and places it on the panel.
This sample grabs a copy of the list value.
I have since modified the sample to add a JButton. I can DnD this onto the panel but it moves it instead of making a copy.
Is there something specific as to why the JButton was moved instead of copied?
What change is required to have the button copied instead of moved?
I even tried pressing the CTRL key as I dragged the button but it still moved it instead of copying.
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.io.IOException;
import javax.swing.*;
public class TestDnD {
public static void main(String[] args) {
new TestDnD();
}
public TestDnD() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JList list;
public TestPane() {
setLayout(new BorderLayout());
list = new JList();
DefaultListModel model = new DefaultListModel();
model.addElement(new User("Shaun"));
model.addElement(new User("Andy"));
model.addElement(new User("Luke"));
model.addElement(new User("Han"));
model.addElement(new User("Liea"));
model.addElement(new User("Yoda"));
list.setModel(model);
add(new JScrollPane(list), BorderLayout.WEST);
//Without this call, the application does NOT recognize a drag is happening on the LIST.
DragGestureRecognizer dgr = DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
list,
DnDConstants.ACTION_COPY_OR_MOVE,
new DragGestureHandler(list)); ///DragGestureHandler - is defined below
///and really just implements DragGestureListener
///and the implemented method defines what is being transferred.
JPanel panel = new JPanel(new GridBagLayout());
add(panel);
//This registers the Target (PANEL) where the Drop is to occur.
DropTarget dt = new DropTarget(
panel,
DnDConstants.ACTION_COPY_OR_MOVE,
new DropTargetHandler(panel), ////DropTargetHandler - is defined below
true); ///and really just implements DropTargetListener
setupButtonTest();
}
private void setupButtonTest()
{
JButton myButton = new JButton("Drag Drop Me");
add(myButton, BorderLayout.NORTH);
DragGestureRecognizer dgr = DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
myButton,
DnDConstants.ACTION_COPY, // ACTION_COPY_OR_MOVE,
new DragGestureHandler(myButton)); ///DragGestureHandler - is defined below
///and really just implements DragGestureListener
///and the implemented method defines what is being transferred.
}
}
public static class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return name;
}
}
////This Class handles the actual item or data being transferred (dragged).
public static class UserTransferable implements Transferable {
public static final DataFlavor JIMS_DATA_FLAVOR = new DataFlavor(User.class, "User");
private User user;
private JButton jbutton;
public UserTransferable(User user) {
this.user = user;
}
public UserTransferable(JButton user) {
this.jbutton = user;
}
#Override
public DataFlavor[] getTransferDataFlavors() {
//Executed as soon as the User Object is dragged.
System.out.println("UserTransferable : getTransferDataFlavors()");
return new DataFlavor[]{JIMS_DATA_FLAVOR};
}
#Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
//This is what is executed once the item is dragged into a JComponent that can accept it.
System.out.println("UserTransferable : isDataFlavorSupported()");
return JIMS_DATA_FLAVOR.equals(flavor);
}
#Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
//Once a Drop is done then this method provides the data to actually drop.
System.out.println("UserTransferable : getTransferData()");
Object value = null;
if (JIMS_DATA_FLAVOR.equals(flavor)) {
if (user != null)
value = user;
else if (jbutton != null)
value = jbutton;
} else {
throw new UnsupportedFlavorException(flavor);
}
return value;
}
}
protected class DragGestureHandler implements DragGestureListener {
private JList list;
private JButton button;
public DragGestureHandler(JList list) {
this.list = list;
}
public DragGestureHandler(JButton list) {
this.button = list;
}
#Override
public void dragGestureRecognized(DragGestureEvent dge) {
//This executes once the dragging starts.
System.out.println("DragGestureHandler : dragGesturRecognized()");
if (dge.getComponent() instanceof JList)
{
Object selectedValue = list.getSelectedValue();
if (selectedValue instanceof User) {
User user = (User) selectedValue;
Transferable t = new UserTransferable(user); ////This is where you define what is being transferred.
DragSource ds = dge.getDragSource();
ds.startDrag(
dge,
null,
t,
new DragSourceHandler());
}
}
else if (dge.getComponent() instanceof JButton)
{
Object selectedValue = dge.getComponent();
if (selectedValue instanceof JButton) {
JButton jb = button;
Transferable t = new UserTransferable(jb); ////This is where you define what is being transferred.
DragSource ds = dge.getDragSource();
ds.startDrag(
dge,
null,
t,
new DragSourceHandler());
}
}
}
}
protected class DragSourceHandler implements DragSourceListener {
public void dragEnter(DragSourceDragEvent dsde) {
//This means you have entered a possible Target.
System.out.println("DragSourceHandler : DragEnter()");
}
public void dragOver(DragSourceDragEvent dsde) {
//Continually executes while the DRAG is hovering over an potential TARGET.
System.out.println("DragSourceHandler : DragOver()");
}
public void dropActionChanged(DragSourceDragEvent dsde) {
}
public void dragExit(DragSourceEvent dse) {
//Executes once the potential target has been exited.
System.out.println("DragSourceHandler : DragExit()");
}
public void dragDropEnd(DragSourceDropEvent dsde) {
//Once the mouse button is lifted to do the drop.
//Executes against any potential drop.
System.out.println("DragSourceHandler : dragDropEnd()");
}
}
protected class DropTargetHandler implements DropTargetListener {
////THESE ARE EXECUTED ONLY WHEN THE MOUSE AND DRAGGED ITEM IS OVER THE TARGET.
private JPanel panel;
public DropTargetHandler(JPanel panel) {
this.panel = panel;
}
public void dragEnter(DropTargetDragEvent dtde) {
System.out.println("DropTargetHandler : dragEnter()");
if (dtde.getTransferable().isDataFlavorSupported(UserTransferable.JIMS_DATA_FLAVOR)) {
//This shows the outline within the TARGET to indicate it will accept the DROP.
System.out.println(" Accept...");
dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
} else {
//If an item is not registered to accept a certain drop this is executed.
System.out.println(" DropTargetHandler : DragEnter() - Else");
dtde.rejectDrag();
}
}
public void dragOver(DropTargetDragEvent dtde) {
//Active while the item is being Dragged over the Target
System.out.println("DropTargetHandler : dragOver()");
}
public void dropActionChanged(DropTargetDragEvent dtde) {
System.out.println("DropTargetHandler : dropActionChanged()");
}
public void dragExit(DropTargetEvent dte) {
//Once the dragged item is taken out of the Target area.
System.out.println("DropTargetHandler : dragExit()");
}
public void drop(DropTargetDropEvent dtde) {
//Once the mouse button is released to do the Drop then this is executed.
System.out.println("DropTargetHandler : drop()");
if (dtde.getTransferable().isDataFlavorSupported(UserTransferable.JIMS_DATA_FLAVOR)) {
Transferable t = dtde.getTransferable();
if (t.isDataFlavorSupported(UserTransferable.JIMS_DATA_FLAVOR)) {
try {
Object transferData = t.getTransferData(UserTransferable.JIMS_DATA_FLAVOR);
if (transferData instanceof User) {
User user = (User) transferData;
dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
panel.add(new JLabel(user.getName()));
panel.revalidate();
panel.repaint();
}
else if (transferData instanceof JButton) {
JButton jb = (JButton) transferData;
dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
panel.add(jb);
panel.revalidate();
panel.repaint();
}
else {
dtde.rejectDrop();
}
} catch (UnsupportedFlavorException ex) {
ex.printStackTrace();
dtde.rejectDrop();
} catch (IOException ex) {
ex.printStackTrace();
dtde.rejectDrop();
}
} else {
dtde.rejectDrop();
}
}
}
}
}
Hi i have been strugguling with this for a while. could you please suggest changes.
public class JobDetails extends Panel implements Serializable {
private static Logger LOGGER = Logger.getLogger(JobDetails.class);
public static final long serialVersionUID = 42L;
private List<Job> list;
#Override
protected void onInitialize() {
super.onInitialize();
}
public JobDetails(String id, final PageParameters params) {
super(id);
FeedbackPanel feedbackpanel = new FeedbackPanel("feedbackpanel");
add(feedbackpanel);
String JOBNUMBER = params.get("jobnumber").toString();
String OBJECTTYPE = params.get("objecttype").toString();
String OBJECTNUMBER = params.get("objectnumber").toString();
if (JOBNUMBER != null) {
LOGGER.info("JOBNUMBER != null");
list = Utils.retrieve(JOBNUMBER);
} else {
list = Utils.retrieve(OBJECTTYPE, OBJECTNUMBER);
}
DataView dataView = new DataView("jobs", new ListDataProvider(list)) {
#Override
public void onConfigure() {
super.onConfigure();
setVisible(getDataProvider().size() > 0);
}
#Override
protected void populateItem(final Item item) {
final Job job = (Job) item.getModelObject();
Link plink = new Link("parentJobLink") {
#Override
public void onClick() {
PageParameters p2 = new PageParameters();
p2.add("jobNumber", job.getParentJob());
JobDetails.this.replaceWith(new ParentJobDetails("innerpanel", p2));
}
};
plink.add(new Label("parentJobLabel", job.getParentJob()));
item.add(plink);
item.add(new Label("jobType", job.getJobType()));
item.add(new Label("whoSubmitted", job.getWhoSubmitted()));
item.add(new Label("objectType", job.getObjectType()));
item.add(new Label("objectNumber", job.getObjectNumber()));
item.add(new Label("objectRevision", job.getObjectRevision()));
item.add(new Label("jobStatus", job.getJobStatus()));
}
};
dataView.setItemsPerPage(20);
add(dataView);
add(new CustomPagingNavigator("navigator", dataView));
if (list.size() == 0) {
***"Replace the Current Panel with new(SearchInnerPanel("innerpanel", params)"***
}
}
}
Scenario: when i search for a job, if a job exists job is displayed in this panel and if the job does not exist it is redirected back to the search panel. i am unable to redirect back to the search panel.
Here is how the code should look really like:
public class JobDetails extends Panel {
private static final Logger LOGGER = Logger.getLogger(JobDetails.class);
public static final long serialVersionUID = 42L;
private List<Job> list;
public JobDetails(String id, final PageParameters params) {
super(id);
FeedbackPanel feedbackpanel = new FeedbackPanel("feedbackpanel");
add(feedbackpanel);
}
#Override
protected void onInitialize() {
super.onInitialize();
PageParameters params = getPage().getPageParameters();
String JOBNUMBER = params.get("jobnumber").toString();
String OBJECTTYPE = params.get("objecttype").toString();
String OBJECTNUMBER = params.get("objectnumber").toString();
if (JOBNUMBER != null) {
LOGGER.info("JOBNUMBER != null");
list = Utils.retrieve(JOBNUMBER);
} else {
list = Utils.retrieve(OBJECTTYPE, OBJECTNUMBER);
}
DataView dataView = new DataView("jobs", new ListDataProvider(list)) {
#Override
public void onConfigure() {
super.onConfigure();
setVisible(getDataProvider().size() > 0);
}
#Override
protected void populateItem(final Item item) {
final Job job = (Job) item.getModelObject();
Link plink = new Link("parentJobLink") {
#Override
public void onClick() {
PageParameters p2 = new PageParameters();
p2.add("jobNumber", job.getParentJob());
JobDetails.this.replaceWith(new ParentJobDetails("innerpanel", p2));
}
};
plink.add(new Label("parentJobLabel", job.getParentJob()));
item.add(plink);
item.add(new Label("jobType", job.getJobType()));
item.add(new Label("whoSubmitted", job.getWhoSubmitted()));
item.add(new Label("objectType", job.getObjectType()));
item.add(new Label("objectNumber", job.getObjectNumber()));
item.add(new Label("objectRevision", job.getObjectRevision()));
item.add(new Label("jobStatus", job.getJobStatus()));
}
};
dataView.setItemsPerPage(20);
add(dataView);
add(new CustomPagingNavigator("navigator", dataView));
if (list.size() == 0) {
replaceWith(new(SearchInnerPanel("innerpanel", params));
}
}
}
But it would be much better if you move the code that retrieves the list to the parent of this panel. If there are items in the list then use JobDetails panel, otherwise use SearchInnerPanel
Hello I created a custom list view and for update used notifyDataSetChanged() method but my list not updated. please help me.
this is my source code
public class fourthPage extends ListActivity {
ListingFeedParser ls;
List<Listings> data;
EditText SearchText;
Button Search;
private LayoutInflater mInflater;
private ProgressDialog progDialog;
private int pageCount = 0;
String URL;
ListViewListingsAdapter adapter;
Message msg;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Bundle b = getIntent().getExtras();
URL = b.getString("URL");
Log.i("Ran->URL", "->" + URL);
MYCITY_STATIC_DATA.fourthPage_main_URL = URL;
final ListingFeedParser lf = new ListingFeedParser(URL);
Search = (Button) findViewById(R.id.searchButton);
SearchText = (EditText) findViewById(R.id.search);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(SearchText.getWindowToken(), 0);
this.getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
try {
progDialog = ProgressDialog.show(this, "",
"Loading please wait....", true);
progDialog.setCancelable(true);
new Thread(new Runnable() {
#Override
public void run() {
try {
data = lf.parse();
} catch (Exception e) {
e.printStackTrace();
}
msg = new Message();
msg.what = 1;
fourthPage.this._handle.sendMessage(msg);
}
}).start();
Search.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
SearchText = (EditText) findViewById(R.id.search);
if (SearchText.getText().toString().equals(""))
return;
CurrentLocationTimer myLocation = new CurrentLocationTimer();
LocationResult locationResult = new LocationResult() {
#Override
public void gotLocation(final Location location) {
Toast.makeText(
getApplicationContext(),
location.getLatitude() + " "
+ location.getLongitude(),
Toast.LENGTH_LONG).show();
String URL = "http://75.125.237.76/phone_feed_2_point_0_test.php?"
+ "lat="
+ location.getLatitude()
+ "&lng="
+ location.getLongitude()
+ "&page=0&search="
+ SearchText.getText().toString();
Log.e("fourthPage.java Search URL :->", "" + URL);
Bundle b = new Bundle();
b.putString("URL", URL);
Intent it = new Intent(getApplicationContext(),
fourthPage.class);
it.putExtras(b);
startActivity(it);
}
};
myLocation.getLocation(getApplicationContext(),
locationResult);
}
});
} catch (Exception e) {
Toast.makeText(getApplicationContext(),
"No data available for this request", Toast.LENGTH_LONG)
.show();
}
}
private Handler _handle = new Handler() {
#Override
public void handleMessage(Message msg) {
progDialog.dismiss();
if (msg.what == 1) {
if (data.size() == 0 || data == null) {
Toast.makeText(getApplicationContext(),
"No data available for this request",
Toast.LENGTH_LONG).show();
}
mInflater = (LayoutInflater) getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
adapter = new ListViewListingsAdapter(getApplicationContext(),
R.layout.list1, R.id.title, data, mInflater);
setListAdapter(adapter);
getListView().setTextFilterEnabled(true);
adapter.notifyDataSetChanged();
} else {
Toast.makeText(getApplicationContext(),
"Error in retrieving the method", Toast.LENGTH_SHORT)
.show();
}
}
};
public void onListItemClick(ListView parent, View v, int position, long id) {
// remember i m going from bookmark list
MYCITY_STATIC_DATA.come_from_bookmark = false;
Log.i("4thPage.java - MYCITY_STATIC_DATA.come_from_bookmark",
"set false - > check" + MYCITY_STATIC_DATA.come_from_bookmark);
Listings sc = (Listings) this.getListAdapter().getItem(position);
if (sc.getName().equalsIgnoreCase("SEE MORE...")) {
pageCount = pageCount + 1;
final ListingFeedParser lf = new ListingFeedParser((URL.substring(
0, URL.length() - 1)) + pageCount);
try {
progDialog = ProgressDialog.show(this, "",
"Loading please wait....", true);
progDialog.setCancelable(true);
new Thread(new Runnable() {
#Override
public void run() {
data.remove(data.size() - 1);
data.addAll(lf.parse());
Message msg = new Message();
msg.what = 1;
fourthPage.this._handle.sendMessage(msg);
}
}).start();
} catch (Exception e) {
pageCount = pageCount - 1;
// TODO: handle exception
Toast newToast = Toast.makeText(this, "Error in getting Data",
Toast.LENGTH_SHORT);
}
} else {
Bundle b = new Bundle();
b.putParcelable("listing", sc);
Intent it = new Intent(getApplicationContext(),
FifthPageTabbed.class);
it.putExtras(b);
startActivity(it);
}
}
#Override
public void onBackPressed() {
setResult(0);
finish();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Log.e("RESUME:-)", "4th Page onResume");
try {
//adapter.notifyDataSetChanged();
//setListAdapter(adapter);
//getListView().setTextFilterEnabled(true);
} catch (Exception e) {
Log.e("EXCEPTION in 4th page",
"in onResume msg:->" + e.getMessage());
}
}
}
Do not re-create the object of ArrayList or Array you are passing to adapter, just modify same ArrayList or Array again. and also when array or arrylist size not changed after you modify adapter then in that case notifydatasetchange will not work.
In shot it is work only when array or arraylist size increases or decreases.
What version of Android are you targeting? The latest version seems to have revised how notifyDataSetChanged() works. If you target sdk 11 it might work?
Also, there seems to be a different (and very thorough answer) to this question in another post:
notifyDataSetChanged example
Hi guys i would like you to help me display parallel arrays on a JScrollPane. The arrays are of String and double data types. Here is my sample code: String[] items = {"fish","frog"}; double[] prices = {12,19}; I'm supposed to put them on the JScrollPane, with the element in position 0 of the items array next to the prices position 0 and so on;
Any reason you can't put your data in JTable and add the table to the scroll pane?
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
class ItemTableModel extends AbstractTableModel {
final String[] items;
final double[] prices;
public ItemTableModel(String[] items, double[] prices) {
checkNotNull(items);
checkNotNull(prices);
checkArgument(items.length == prices.length);
this.items = items;
this.prices = prices;
}
#Override
public int getRowCount() {
return items.length;
}
#Override
public int getColumnCount() {
return 2;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return items[rowIndex];
case 1:
return prices[rowIndex];
default:
throw new IllegalArgumentException();
}
}
#Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return String.class;
case 1:
return Object.class;
default:
throw new IllegalArgumentException();
}
}
#Override
public String getColumnName(int columnIndex) {
switch (columnIndex) {
case 0:
return "Item";
case 1:
return "Price";
default:
throw new IllegalArgumentException();
}
}
}
public class Example {
public static void main(String[] args) {
Runnable createAndShowGui = new Runnable() {
#Override
public void run() {
createAndShowGui();
}
};
SwingUtilities.invokeLater(createAndShowGui);
}
private static void createAndShowGui() {
String[] items = { "fish", "frog" };
double[] prices = { 12, 19 };
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
ItemTableModel tableModel = new ItemTableModel(items, prices);
JTable table = new JTable(tableModel);
//table.setTableHeader(null); // uncomment to hide the table header
frame.setContentPane(new JScrollPane(table));
frame.pack();
frame.setVisible(true);
}
}