How do I use the results of an action?
I'm trying to pass some information from user inputs back into my code but I don't really know how to go about it.
Basically, I'm making a Swing application that builds an XML file with a lot of repetitive lines and the idea is that the user will be able to input the unique values for each line, and the program will fill in the rest.
I have a dialog open with several text fields for the user to input information, once the user is done, I store the contents of these fields in a
List
and then (after checking for bad input) use the List
to create an object with the user data in the fields. I then need to add the toString of that object to the next line of my final output.
The problem is, the information doesn't exist until the user presses the button, I don't know how to tell my code to "wait" until the button is pressed before continuing execution.
I guess I'm trying to use swing to make my own, more complicated JOptionpane.showInputDialogue
, where instead of returning a String it returns a list of Strings, but it still pauses execution until the strings are confirmed.95 Replies
⌛
This post has been reserved for your question.
Hey @Devin! Please useTIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here./close
or theClose Post
button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.
what if the user modifies one of the previous fields?
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.
Clicking the button to confirm the contents of the fields would close the dialog and open the next one
then the UI could call the code doing the XML thing whenever doing what
which part of that is the problem?
XML streaming?
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.
The problem isn't calling it, I guess my issue is my loop is in the wrong place?
idk you haven't told me what issue you are facing
but maybe you want some system with listeners
or something where the background functionality "waits" on the UI, e.g. using a
BlockingQueue
Okay so I have a main method running all the logic, and then another one in a different class that makes the UI show up.
This is for like, building an input display using XML and custom images
Is all the logic really in the main method?
no the logic is mostly elsewhere, I don't know what to call what goes in main
god this is sloppy, I'd send a code snippet but I doubt it means anything unless I comment it.
Basically I have a loop in main that sets
currentInput
to be a CustomInput
(which is an object I made for this), and it does this by calling the class that opens the window in the UI classSo I want the UI class to open the window, collect the information, and then return an object created with that information
so then I can call the
toString
method of that object to print the next line to my XML file.I guess this is really where the issue lives
I display a prompt, and then I need the results of what the user inputs before returning to main
then call some method in every iteration that does the updating?
or you could have a
BlockingQueue
and two threads: The thread doing the UI logic inserts elements (input) and the other thread that performs the logic takes the elements out of the queueHow do I tell things which thread to use?
I have it set up like this right now, but for some reason none of the UI elements appear in the window
this is despite the fact that they are all added before I changed the code
Notably, it DOES work if I run it from outside of my main loop with similar parameters???
It works with the same inputs in a loop
as long as I run it from main
which
why does the same code do different things in different places?
is it because the other view is already open???
This is the ENTIRE method
what part of this code is breaking the window??
it has to be something here, because if it was an issue in the UI class, it would still happen when I call
DisplayBuilderUI.ShowPromptWindow
from main
is it because I have a FileInputStream
and FileOutputStream
open?
like
I can't fathom why the window is just frozen with no UIif you are doing something else in the thread handling the UI, it will freeze until it's done
how do I know what thread I'm using for what?
you could do something like that
making sure both threads share the
BlockingQueue
I am not at all familiar with BlockingQueue, I don't know how to use one.
BlockingQueue
is a Queue
meaning you can insert elements and take them out in the order of insertion (first in first out)It needs to be a field of the class
should it be in my main class or my UI class?
BlockingQueue
s have the ability that you can do that with in a way that it waits for the elements to be inserted
you can have them in different classes
as long as both have the same BlockingQueue
I can put BlockingQueues in different classes as long as they have the same BlockingQueue?
yes
uh
does it need a thread to wait for the thing to happen?
okay
I don't get all of it yet, but let me know if I'm on track here
I have
This is sitting in my fields. I'm not waiting for individual strings, but a whole
CustomInput
object, so I made it take those.
all the strings will be ready at the same time
thenyeah you can also do something else
I replaced the commented code in my
showPromptWindow
method with thisand then here I offer the queue a button instead of setting the
currentInput
to a button directlymaybe consider one big try catch over all the
queue.take()
calls
I meant you would call offer()
whenever you get user inputI only have one take call,
I don't collect the user input one box at a time
the user input becomes the button
whenever you want the next user input, call
take()
like you would do with Scanner#nextLine
and whenever you get new user input, you offer()
I think that is what I am doing. User Input is like, 5 strings that are all submitted at once
next user input would be the same
I don't know how it would help to only accept one string at a time, the choke point comes in before the user is allowed to input anything at all.
You mean 5 inputs for one button?
yeah
hold on
if you have a variable number of inputs per button, you could also use a
String[]
oh ok it's always the same
I'll always know how many inputs I'm looking at. Each input type has it's own toString Method that knows how to handle any case.
The number of available fields is determined by an input type ID
Here's a little UML diagram I made of only the CustomInput class and it's children
idk if it's helpful to you but now you have it.
Anyway, I know that if the user inputs information and clicks the button, everything after that works
All I need is for the user to be shown the text fields.
So the approach works?
approach?
here's what happens when I run the code outside of that little debug thing I showed you
I think it MAYBE has to do with the output stream trying to use the same thread that's supposed to handle drawing the UI??
In which case I could just use a StringBuilder to assemble the output and then print it all to the file as one massive string after I'm done collecting input
but that's a pain in the ass I don't want to have to refactor for unless I know it would fix things.
Oh, but the sample video I sent you DID use the
BlockedQueue
version of the code instead of the while loop with delay
so at least that's working lolWhat is the UI code there?
like where are you showing the window that freezes?
Oh
The window is generated separately every time because it needs to have different fields depending on the inputType parameter
but more specifically, it shows right near the bottom at
promptFrame.setVisible(true)
Why does the UI class run
take()
?Because it needs the ButtonInput to pass back to main
Is there a better way to pass it back??
What do you mean with passing it back?
take() waits until there is an element in the queue and removes it once there is one
Correct
Main.startBuild calls the method I just shared and expects a
CustomInput
to be returned.
The method has to wait for the user to finish entering the information, once the user clicks the "Done" button, a CustomInput
object exists, but it does not exist before the user presses the button, so we need to wait for that to happen.
The BlockedQueue is waiting for a CustomInput object to exist before continuing execution, without it the code would immediately try to return null
, which is the default value of the object
Window opens → We wait for a CustomInput
from the queue → User fills all fields → user presses "Done" → We use all the information from the user input to create a CustomInput
→ we add the CustomInput
to the queue → the queue now contains a thing, execution resumes from there.
This part actually works correctly, the blockedqueue is doing it's job
the problem is that the "Window Opens" step does not show us any of our text fields
Even though we've seen it work when I call it from Main.main
Is this not a sensible application of the BlockedQueue?Yeah but
showPromptWindow
is the UI thing, right?
Why would that wait/take something out of the queue?
Isn't that supposed to insert stuff?no
Because it isn't a button handler
The UI does not make the
CustomInput
The code makes the CustomInput
using information collected from the UILike, this is how the button is constructed
What on earth would I be putting into the queue before I have collected the information?
Each type of
CustomInput
will have it's own method that builds it
and the user clicking the "Done" button will call the appropriate one
I don't know how I could possibly populate the queue without leaving the method that opens the window
Since the CustomInput is created between the window being opened and the queue being read from, I literally NEED to have that method on hold while the button is getting created
it's the only place in the whole program I CANNOT populate the queue.I feel like something about this flow would have to be fundamentally different for what you're describing.
Like, would you have the CustomInput constructor send the input directly back to Main via a setter?
And if so, would making that change do anything to help me resolve the window issue?
I suggested to make the UI and logic to run in independent threads
but I don't really know what the problem is
How do I make them use independent threads?
Like, why are they running on the same thread to begin with?
maje the UI not be dependent on the logic
Do you really need to return the user input thing from the UI?
You only use the blocking queue for sending things from the UI to the logic
that was my idea
So like, I have a blocking queue in Main, and the last method in the logic populates that queue?
yes
if you want to use two threads
Does the UI need anything from the logic?
The UI only needs to know what type of input prompt to display, which is passed in from Main as an
int
so the UI doesn't have any reason to take anything out of the queue, right?
I guess, the only reason it does is to return it to the logic immediately
so I could just make the prompt return void
Hmm
the one issue is that I no longer have any way to know when to dismiss the dialog
other than making it a field
?
Like, once I get the
CustomInput
back, I close the input windowDoes the method create the CustomInput object?
A different method creates the object
I can't close the input dialog from a different method though
it's local to the method that displays it
you can put it in the queue and also store it
Alright, I moved the queue back to logic, but still same problem
?
Instead of returning a
CustomInput
, the promptWindow method returns nothingok
Instead I have the button action handler use a setter in Main to offer the input to the queue
here's the setter method
And here's my updated while loop, which is now in a try/catch block
but the UI still doesn't render
same as in the video I sent of it not working
so the UI isn't responding?
no
also my debug case no longer works
It either puts every UI element twice in the 2nd prompt or provides a completely empty window
which is probably because the logic that cleared out the List of fields and emptied out the frame is no longer delayed until input is received
I have no good place to put these 2 lines anymore
?
It looks like you are having issues with debugging or issues that can be solved using a debugger.
Check out this article on dev.java to see how debugging works and how to use a debugger.
This Stack Overflow question and its answers also explain debugging in general.
These links describe how to use the debugger in some IDEs:
• Debugging in IntelliJ
• Debugging in Eclipse
if you don't know how to use debuggers
💤
Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived.
If your question was not answered yet, feel free to re-open this post or create a new one.
In case your post is not getting any attention, you can try to use /help ping
.
Warning: abusing this will result in moderative actions taken against you.