I have a page that has a button to download information in the format of a CSV file. The button opens a confirm dialog to download the file. I need to store that file to a temporary location (whether that be memory or saving to an actual file and then deleting it after) and then read the data in the CSV to an array.
I've tried the code in these questions (question 1, question 2, question 3, and question 4), and it's not quite what I need - mostly because they weren't downloading a CSV and using the data in it.
I'm not sure that the ConfirmDialog is being opened, but I did add a ConfirmHandler returning true to attempt to download the file. However, I don't know where the file is downloading if it is at all.
Here's what I have happening and where I get stuck:
I log in just fine. I go to a report generator. I generate a report that opens in a new window. The new window opens fine and I catch it with a WebWindowListener. I then search for the "save as CSV" button on the new window. I can find that, and I can click on it, but a System.out.print call shows that the ConfirmHandler isn't firing.
for (DomElement e : newPage.getElementsByTagName("button")) {
int i = 0;
webClient.setConfirmHandler(new ConfirmHandler() {
private static final long serialVersionUID = 1L;
#Override
public boolean handleConfirm(Page arg0, String arg1) {
System.out.println("Test"); //isn't firing
return false;
}
});
if (((HtmlButton) e).getAttribute("onclick").contains("CSV")) {
((HtmlButton) e).click();
}else {
if (i++ == (newPage.getElementsByTagName("button").size() - 1)) throw new AssertionError("CSV button not found");
}
}
The inspiration for this answer came from this answer.
I really wanted to get the CSV information without downloading the file, and so I, inside of the webWindowContentChanged(arg0) method of my webWindowListener, just used arg0.getWebWindow().getEnclosingPage().getWebResponse().getContentAsString() and then used String.split() a couple times to get the information I wanted.
Here's what the code looks like so it's a little clearer:
webClient.addWebWindowListener(new WebWindowListener() {
#Override
public void webWindowContentChanged(WebWindowEvent arg0) {
if (CSVclicked) { //boolean that is set true when I click the download button...
String CSV = arg0.getWebWindow().getEnclosedPage().getWebResponse().getContentAsString();
//do things...
CSVclicked = false; //don't use the same behavior next time the method is called...
}
}
});
Related
I have a problem with updating JProgressBar:
//Start to search for files on drives
private void searchForDICOMFIles2(ArrayList<String> foundDriveLetters)
{
//Thread 1 - search for DICOM files and add them to array
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
////here is the problem
for (String currentDriveLetter_2:foundDriveLetters)
{
File currentDrive_2 = new File(currentDriveLetter_2);
checkFilesAndFoldersForDICOMFiles(currentDrive_2);
}
//updating here will work
Screen_ImportingFiles.setCheckMarkForTaskLabel(1);
Screen_ImportingFiles.updateProgressBar(25, 1, true);
} catch (Exception e) {
e.printStackTrace();
Method checkFilesAndFoldersForDICOMFiles is a huge FOR loop which iterates through files on drive and searches for DICOM files based on extension and if there is no extension, it tries to read the file to determine if it is DICOM or not. Based on the number of files, it also wants to display progression of file checking (i.e. 50% would mean it checked 150 file out of 300). When I want to update progress bar from this method it is not updating progression Bar on JFrame.
Is there a way how to update progress bar like this?
I have rename dialog for rename file
String renameTo = JOptionPane.showInputDialog(gui, "New Name", currentFile.getName());
it works this way, but I have a problem.
the problem is that I set the default value with the extension of the file
but I just want the file name to be selected.
sample : my file name = yusuf.png
I want select only yusuf like;
There is a lot going on inside JOptionPane, it's one of the things that makes it so powerful, it also makes it a little inflexible to.
Two immediate problems are apparent...
You can't gain direct access to the JTextField been used to get input from the user
The JOptionPane wants to control which components have focus when the dialog is first shown.
Setting up the JTextField is actually straight forward...
String text = "yusuf.png";
int endIndex = text.lastIndexOf(".");
JTextField field = new JTextField(text, 20);
if (endIndex > 0) {
field.setSelectionStart(0);
field.setSelectionEnd(endIndex);
} else {
field.selectAll();
}
This will basically select all the text from the start of the String up to the last . or all the text if no . can be found.
The difficult part now is taking back focus control from the JOptionPane
// Make a basic JOptionPane instance
JOptionPane pane = new JOptionPane(field,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION,
null);
// Use it's own dialog creation process, it's simpler this way
JDialog dialog = pane.createDialog("Rename");
// When the window is displayed, we want to "steal"
// focus from what the `JOptionPane` has set
// and apply it to our text field
dialog.addWindowListener(new WindowAdapter() {
#Override
public void windowActivated(WindowEvent e) {
// Set a small "delayed" action
// to occur at some point in the future...
// This way we can circumvent the JOptionPane's
// focus control
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
field.requestFocusInWindow();
}
});
}
});
// Put it on the screen...
dialog.setVisible(true);
dialog.dispose();
// Get the resulting action (what button was activated)
Object value = pane.getValue();
if (value instanceof Integer) {
int result = (int)value;
// OK was actioned, get the new name
if (result == JOptionPane.OK_OPTION) {
String newName = field.getText();
System.out.println("newName = " + newName);
}
}
And, crossing our fingers, we end up with something looking like...
Personally, I'd wrap this up in a nice reusable class/method call which returned the new text or null based on the action of the user, but that's me
Isn't there an easier way?
Of course, I just like showing you the most difficult solution possible ... 😳 (sarcasm) ... it's kind of why I suggested wrapping it up in it's own utility class, so you can re-use it later 😉
I am currently using Vaadin 7.3+ and want to validate in a text field as the user types in real time.
This is what I tried so far:
textField.setTextChangeEventMode(TextChangeEventMode.LAZY);
textField.setNullRepresentation("");
textField.addTextChangeListener(new FieldEvents.TextChangeListener() {
#Override
public void textChange(FieldEvents.TextChangeEvent event) {
for (Validator v : textField.getValidators()) {
try {
v.validate(event.getText());
} catch (InvalidValueException e) {
log.warn("validation error: " + e.getMessage() + " and value was: {}", event.getText());
}
}
}
});
The problem is that although all the validators are being executed and validation is being done the red error indicator is not rendered until the focus leaves the field, i.e. the user hits enter or clicks somewhere else. I tried adding textField.markAsDirty but this did not work. Does anyone know of a solution to this problem? Or of a better solution in general for creating a real time validator on a text field?
Thanks in advance for your time and input :-)
Validators in core the Vaadin are not designed to work while typing, which is a shame for a RIA framework. This will hopefully be fixed in upcoming version. Making it work well today with core components is bit tricky, but doable. Your own solution probably has some UX issues if there is some latency between your server and the client - the cursor might jump into unintended place if user starts to retype again while validator is executed. I have worked on this a lot in Viritin add-on. By using its AbstractForm (or raw MBeanFieldGroup) together with MTextField this should work pretty well and without any configuration. You can try that solution with e.g. this example.
the problem here is, that the event sends the text, but does not actually modify the value of the input. the easiest way to go around this would be setting the value. e.g.
addTextChangeListener(new FieldEvents.TextChangeListener() {
#Override
void textChange(FieldEvents.TextChangeEvent event) {
final textField = event.source as TextField
textField.value = event.text
}
})
this would just trigger the change of the field and also the validators and all will go down to the client as expected.
edit
as you stated in the comments, the cursor pos should be kept. You can just validate the text from the event with whatever means you need. Key point here is, to just set the componentError of the field to get the error down the line for the field.
#Override
void textChange(FieldEvents.TextChangeEvent event) {
final tf = event.source as TextField
try {
tf.validate(event.text) // this works in groovy! not java.
tf.setComponentError(null)
}
catch (InvalidValueException e) {
tf.setComponentError(new SystemError(e))
}
}
This straight forward workaround solution seems to work fine although it is quite inelegant.
textField.setTextChangeEventMode(TextChangeEventMode.LAZY);
textField.setNullRepresentation("");
textField.addTextChangeListener(new FieldEvents.TextChangeListener() {
#Override
public void textChange(FieldEvents.TextChangeEvent event) {
try {
textField.setValue(event.getText());
// workaround cursor position problem
textField.setCursorPosition(event.getCursorPosition());
textField.validate();
} catch (InvalidValueException e) {
log.warn("validation error: " + e.getMessage() + " and value was: {}", delegate.getValue());
}
}
});
Take a look in the Vaadin Documentation. If I get you right it should be fine to set your field in immediate mode. Sometimes it is recommend to allow null values to avoid unnecessary warnings.
TextField field = new TextField("Name");
field.addValidator(new StringLengthValidator(
"The name must be 1-10 letters (was {0})",
1, 10, true));
field.setImmediate(true);
field.setNullRepresentation("");
field.setNullSettingAllowed(true);
I've managed to add an image into a JPanel in netbeans and display it.I wonder how to get to the next one,by pressing a button.
I've added the image using this code:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){
// TODO add your handling code here:
JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(null);
if ( result == JFileChooser.APPROVE_OPTION ){
String Ruta = fileChooser.getSelectedFile().getAbsolutePath();
jTextField1.setText(Ruta);
Icon icon = new ImageIcon(Ruta);
jLabel2.setIcon(icon);
JOptionPane.showMessageDialog(this,"You chose to open this file: " +
fileChooser.getSelectedFile().getName());
}
}
And when i press a button called "jButton2" to get the next image,without manually selecting it again from folder.
For example:
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt){
// TODO add your handling code here:
}
Thank You very much.
You have to enumerate images in the directory you are browsing in. When the user selects the file, you should keep a list of all images from that directory in order to retrieve them when user click the next button. As well you can get the file list whenever the user clicks the next button.
maybe something like this:
private File allFiles;
private int currentIndex;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(null);
if ( result == JFileChooser.APPROVE_OPTION ){
currentFile = fileChooser.getSelectedFile();
String Ruta = currentFile.getAbsolutePath();
jTextField1.setText(Ruta);
allFiles = currentFile.getParent().listFiles(); // maybe you need a filter to include image files only....
currentIndex = indexOf(allFiles, currentFile);
Icon icon = new ImageIcon(Ruta);
jLabel2.setIcon(icon);
JOptionPane.showMessageDialog(this,"You chose to open this file: " + fileChooser.getSelectedFile().getName());
}
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
if (currentIndex+1 < allFiles.length) {
jtextField1.setText(allFiles[++currentIndex]);
}
}
private int indexOf(File[] files, File f) {
for (int i=0; i+1 < files.length; i++) {
if (files[i].equals(f)) {
return i;
}
}
return -1;
}
Get the parent file if the current image (File.getParent()).
Use one of the File.list..() methods to get the image files.
Sort them into some order that means 'next' to the user.
Iterate that connection until you find the current File then display the next one after that.
I am assuming that you want the next image, if possible in the same directory you chose in your first code excerpt. What you could do is that once the user has chosen the image, you could use Apache's FileUtils to get the extension of files. If the file is a JPG, JPEG, PNG, etc you could load it's location in a List of strings.
This will give you a list of picture paths. You could then use the buttons to traverse the list. Once the button is pressed, you move to the next item, load the image and render it.
EDIT: This is how I would go about it step by step:
Create a global variable of type List.
Create a global variable which will act as a counter;
In your jButton1ActionPerformed method:
Get the parent directory of the file that the user has chosen;
Use Apache's FileUtil class to get the extension of the file names. If the file name is an image, such as PNG, JPG, etc, add it (the path of that file) to your list.
In you jButton2ActionPerformed, increment the counter (if the counter is not smaller than the size of your list, re-initialize it to 0, so as to avoid OutOfBoundsExceptions) and load the the file denoted by the counter using similar logic to your jButton1ActionPerformed method.
1) I am using a ListView to populate some 2 labels from database. The table has 100 rows so I get 100 <TD>s. This works fine.
this.selectView = new PageableListView("selectedBG", new PropertyModel(this, "selectedList"), 10) {
private static final long serialVersionUID = 1L;
#Override
protected void populateItem(final ListItem item){
selParentGclOrg = new Label("selParGclOrgId", new PropertyModel(gclOrg, "parentGclOrgId"));
selParentGclOrg.setOutputMarkupId(true);
final AjaxLink ajl = new AjaxLink("clickMe"){
public void onClick(AjaxRequestTarget target){
chilgGcl = gclOrg.getGclOrgId();
selectPopUp.show(target);
}
};
ajl.add(selParentGclOrg);
final Label lblGclOrg = new Label("selGclOrgId", Integer.valueOf(gclOrg.getGclOrgId()).toString());
item.add(ajl);
item.add(lblGclOrg);
}
}
2) One label is hyperlinked and opens a popup window from which I can select possible values for label 2. The popup window opens perfectly.
selectPopUp = new select_popUP("showModal",container){
#Override
public void onSelect(AjaxRequestTarget target, int gclOrgId){
selParentGclOrg.setModelObject(Integer.toString(gclOrgId));
target.addComponent(selectView);
close(target);
}
#Override
public void onCancel(AjaxRequestTarget target){
close(target);
}
};
3) In the popup window, possible values are hyperlinked. Clicking on it closes the popup window and sends the possible value to the main page. This works ok... I think.
4) The new value is assigned to Label 2 using:
target.addComponent(selectView);
This is where I am getting stuck. Wicket is supposed to change the label on the same row (at least, I think) but it's updating the Label 2 of the last row.
What am I doing wrong?
I haven't run through your logic for selecting rows, but I believe my solution to a similar issue will help you. The problem is that ListViews don't automatically refresh each of their rows individually when AJAX requests come in. The solution I used was to wrap the whole shebang in a WebMarkupContainer. When that's done, everything will get regenerated on the request.
I think the relevant parts of your code are missing from the post...
Like:
where gclOrg is set
where selParentGclOrgis set for the ModalWindow
Judging from what I can see, I would put my bet on an issue with populateItem beeing run way after the rest of the code in your class... Most of your code will be run on constructor time or onBeforeRender, populateItem will be called sometimes during rendering... But that's just a wild guess.