JavaFX ScrollPane - speed up swiping effect on touch device - java

I found that if I swipe within a ScrollPane in a JavaFX application on a touch device, the scroll-animation is quite slow. I do not swipe over the ScrollBar of the ScrollPane but within the content itself.
How can I speed up the swipe animation?

This is a known problem with touch devices and the ScrollPane ;)
If you want to speedup the animation you have to set the position by your own.
I solved the same problem I while ago on this way, worked well.
You need to do something like this:
ScrollPane scrollPane = new ScrollPane();
final IntegerProperty vValueProperty = new SimpleIntegerProperty(0);
final int steps = 5;
scrollPane.vvalueProperty().bind(vValueProperty);
scrollPane.setOnSwipeDown(new EventHandler<GestureEvent>() {
public void handle(GestureEvent event) {
// calculate the needed value here
vValueProperty.set(vValueProperty.get() + steps);
}
});
If the normal swipe animation disturbes you, just kill the event with
event.consume();
But it could be that you need to use an EventFilter in this case cause the EventFilter is called before the Event is doing anything. Can't remember if a consume() at the end of the EventHandler is enough. If not you need to use something like this:
scrollPane.addEventFilter(SwipeEvent.SWIPE_DOWN,
new EventHandler<SwipeEvent>() {
public void handle(SwipeEvent event) {
vValueProperty.set(vValueProperty.get() - steps);
event.consume();
}
});
Well this is just to speedup the animation. If you want your Pane following your finger, just save the first value, which you get OnTouchDetected and calculate the Offset OnTouchMoved. This is your value you can use to translate the Pane correctly. :)
Hope it is useful. I don't have a touch device here to test it.

Related

adding text box on top of gwt java

I am currently working on a school project where we are creating a GWT web application which uses a GeoChart widget to display information about the servers we have crawled. Simply put, I would wish to create a text box on top of our GeoChart widget which shows an interactive world map that takes up the whole screen right now to input information. I have searched quite extensively but I have been unable to come up with an answer.
Here is the code as follows:
#Override
public void onModuleLoad() {
dataReader = (DataReaderAsync) GWT.create(DataReader.class);
RootLayoutPanel.get().add(getSimpleLayoutPanel());
// Create the API Loader
ChartLoader chartLoader = new ChartLoader(ChartPackage.CORECHART);
chartLoader.loadApi(new Runnable() {
#Override
public void run() {
getSimpleLayoutPanel().setWidget(getGeoChart());
drawGeoChart();
}
});
}
As GeoChart is a widget, it is wrapped under(i am not sure if this is the right word) a SimpleLayoutPanel right now which will display it into a full screen. As stated above, I would wish to include text above the geoChart. From my understanding, I would need to create another widget containing my text and add both the GeoChart widget and the text box widget into it. What would be the best way to go about doing this?
I believe DialogBox could solve your problem. People usually program the DialogBox in a way that it only pops up into display when certain event is triggered and disappears after user finishes some operation. In your particular case, you can simply make the DialogBox shows up from the beginning and never disappears. And the best part of it: you don't need to add the DialogBox widget to the geoChart widget. Calling dialogBox.center() or dialogBox.show() will do the magic for you.
Here is the sample code.
#Override
public void onModuleLoad() {
dataReader = (DataReaderAsync) GWT.create(DataReader.class);
RootLayoutPanel.get().add(getSimpleLayoutPanel());
// Create the API Loader
ChartLoader chartLoader = new ChartLoader(ChartPackage.CORECHART);
chartLoader.loadApi(new Runnable() {
#Override
public void run() {
getSimpleLayoutPanel().setWidget(getGeoChart());
drawGeoChart();
}
});
// NOTE: the first argument 'false' makes sure that this dialog box
// will not disappear when user clicks outside of it
// NOTE: the second argument 'false' makes sure that mouse and keyboard
// events outside of the dialog box will NOT be ignored
DialogBox dialogBox = new DialogBox(false, false);
DialogBox.setText("Demo");
HorizontalPanel panel = new HorizontalPanel();
panel.setSpacing(5);
InlineLabel labelOfTextBox = new InlineLabel("Label");
TextBox textBox = new TextBox();
panel.add(labelOfTextBox);
panel.add(textBox);
dialogBox.setWidget(panel);
// show up in the center
dialogBox.center();
}
Dear all thanks for answering my question. To rectify this problem, I have made use of the custom widget API within GWT(known as Composite). Here's the code as below:
private static class CombinedWidget extends Composite {
public CombinedWidget() {
// place the check above the text box using a vertical panel.
VerticalPanel panel = new VerticalPanel();
DockLayoutPanel dPanel = new DockLayoutPanel(Unit.EM);
panel.setSpacing(13);
panel.add(nameProject);
nameProject.setStyleName("gwt-Group-Label");
panel.add(className);
panel.add(nameKs);
panel.add(nameEsmond);
panel.add(nameBowen);
panel.add(nameAaron);
dPanel.addWest(panel, 13);
dPanel.add(getGeoChart());
// all composites must call initWidget() in their constructors.
initWidget(dPanel);
setWidth("100%");
}
Actually I sort of changed from the original idea. Instead of putting it on the very top, I attached the labels into a VerticalPanel and then created a CombinedWidget(custom widget) which adds both a VerticalPanel and DockLayoutPanel together. I then added the VerticalPanel(containing all the labels) and the GeoChart into the DockLayoutPanel.
This solved my problem of displaying both the labels and the GeoChart on the same page(as originally i added it into a VerticalPanel but it would not work as the app would not read the GeoChart due to the VerticalPanel being overlayed on top of the GeoChart).
If you guys want a picture of my app to visualise, please say so!

Java jLabel drag and drop from netbeans "events" context menu

I'm trying to drag a jLabel around the screen following the mouse pointer. As I am no expert on GUI programming I'm trying to do it using Netbeans' GUI design facilities.
I click on "events-mousemotion-mousedragged" and then insert the following code:
private void jLabel2MouseDragged(java.awt.event.MouseEvent evt) {
int x=evt.getX();
int y=evt.getY();
jLabel2.setLocation(x, y);
jLabel2.repaint(); }
I don't expect this simple piece of code to work marvels, the issue however is that it behaves in an erratic manner, the jLabel pops up and flickers almost everywhere within its container.
If it's of any help, layout is set to absolute.
Thanks.
As MadProgrammer pointed out, that was the issue. This is my mouse drag method:
private void jLabel2MouseDragged(java.awt.event.MouseEvent evt) {
Point p = SwingUtilities.convertPoint(evt.getComponent(), evt.getPoint(), getContentPane());
int x=p.x;
int y=p.y;
jLabel2.setLocation(x-120, y-120);
jLabel2.repaint();
}
The jLabel now moves smoothly.
My label is roughly 240x240 pixels, so I corrected the coordinates to have the center of the label placed where the mouse pointer is.
Thanks!

How to resize Swing control which is inside SwingNode in JavaFX8?

How to resize Swing control which is inside SwingNode in JavaFX8?
Sometimes, I has controls resized inside SwingNode. But SwingNode seems to resist this.
It is said in resize() apidoc, that
Applications should not invoke this method directly. If an application
needs to directly set the size of the SwingNode, it should set the
Swing component's minimum/preferred/maximum size constraints which
will be propagated correspondingly to the SwingNode and it's parent
will honor those settings during layout.
But apparently it does not work.
Example code is below.
The question is: how to allow control to turn bigger?
public class Try_Sizes_01 extends Application {
private static final Logger log = LoggerFactory.getLogger(Try_Sizes_01.class);
private static final String text = "Very Long Text For Appear On Button ";
private static int position = 7;
//private JButton button = new JButton("short");
private JButton button = new JButton(text.substring(0, position));
private SwingNode swingNode = new SwingNode();
{
swingNode.setContent(button);
}
#Override
public void start(Stage stage) throws Exception {
Group group = new Group();
group.getChildren().add(swingNode);
Scene scene = new Scene(group);
stage.setTitle("Try_Sizes_01");
stage.setScene(scene);
stage.show();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
/*
button.setText(button.getText() + text.charAt(position));
position++;
if( position >= text.length() ) {
position=0;
}
*/
button.setPreferredSize(new Dimension((int)button.getPreferredSize().getWidth()+10, (int)button.getPreferredSize().getHeight()));
button.setMinimumSize(new Dimension((int)button.getPreferredSize().getWidth(), (int)button.getPreferredSize().getHeight()));
//button.revalidate();
//button.setBounds(0, 0, (int)button.getBounds().getWidth()+10, (int)button.getBounds().getHeight());
Platform.runLater(new Runnable() {
#Override
public void run() {
//swingNode.autosize(); // does not work
//swingNode.resize(button.getBounds().getWidth(), button.getBounds().getHeight()); // does not work and cancels button resizing
//swingNode.setContent(button); // works sometimes but imperfect
}
});
log.info("Swing thread");
log.info("Preferred width is now = {}", button.getPreferredSize().getWidth());
log.info("Bounds width is now = {}", button.getBounds().getWidth());
}
}).start();
}
});
}
public static void main(String[] args) {
launch(args);
}
}
After fighting for hours with basically the same issue, I finally figured out what was going on.
Basically, the problem is that the parent of the SwingNode is trying to set its size when layout occurs, based on the size of the parent. So when you resize your button, and then trigger a layout, the parent of the SwingNode sets it back to its default size. This is occurring because SwingNode overrides the isResizable() method to return true, giving permission to its parent objects to resize it.
In order to avoid this, you can:
Create a custom subclass of SwingNode which overrides isResizable() to false,
or:
Call setAutosizeChildren(false) on the Group which contains the SwingNode.
The latter technique will probably need to be used if you are defining your classes in FXML.
Note, by the way, that you can still call resize(width,height) on a SwingNode even if it overrides isResizable() to false.
I'm not sure if its exactly the same case, but seems related in the sense of getting swing components to size properly with the parent containers. In my case I had a SwingNode containing a JFreeChart (ChartPanel), which I simply couldn't get to resize properly when the parent frame (a border pane within a SplitPane) was itself resized. In the end i simply added a listener to the height/width properties:
pane.widthProperty().addListener((w,o,n)->c.resizeChart((int)n.intValue(), (int)pane.getHeight()));
pane.heightProperty().addListener((w,o,n)->c.resizeChart((int)pane.getWidth(), (int)n.intValue()));
Nothing else I tried could emulate this.
Thanks
I found the pane listener helps but due to the proprietary nature of my component it still didn't resize. I was using fxml and attempting to place the SwingNode inside a Pane for layout purposes. I then I noticed a number of the examples used a StackPane rather than just a Pane and suddently have just made this change the code worked. This was inside a AnchorPane which also seemed to ensure the initial display of the component filled all the available space. In summary a StackPane within the AnchorPane with all the Anchors set to 0 ensured the controlled filled all the initial available space and then did all the resizing, when the manual resize listeners where added it all started working.
pane.widthProperty().addListener((w,o,n)->c.resizeChart((int)n.intValue(), (int)pane.getHeight()));
pane.heightProperty().addListener((w,o,n)->c.resizeChart((int)pane.getWidth(), (int)n.intValue()));

Perform action when button clicked once and do a different action when clicked twice, three times etc. (Netbeans, Java)

I am fairly new to Java programming and want to make a basic game that shows an image when clicked once, a different image when clicked twice and etc.
I know how to do all this but I don't know how to keep track of how any clicks and then do an actions based on how many clicks have been done (Hard to explain, my apologies...)
I ... want to make a basic game that shows an image when clicked once, a different image when clicked twice and etc. I know how to do all this but I don't know how to keep track of how any clicks
As per my comment, give the class with the ActionListener an int field, say called buttonCount, and increment it each time the button is pressed -- inside of the button ActionListener's actionPerformed method: buttonCount++
and then do an actions based on how many clicks have been done (Hard to explain, my apologies...)
In the ActionListener's actionPerformed method change the image displayed. How you change it all depends on how you show it, something that you've yet to show us, and so I can't give you any code.
One way to make it easy is to create an ArrayList of ImageIcons to hold your images (as ImageIcons of course), and then call get(buttonCount) on the ArrayList to get the appropriate ImageIcon and display it in a JLabel via its setIcon(...) method. Make sure that the buttonCount is less than the size of the ArrayList so as not to get an ArrayIndexOutOfBoundsException. One way to do this is to mod your buttonCount by the size of the ArrayList. This will allow you to cycle through your collection of images.
Again, you will want to read the Swing tutorials on how to use JButtons and then break down your big problem into small steps, trying to solve each step one at a time.
Again if you need greater detail and more specific help, then you must show what you've tried and explain in detail what problems you may be having with it. It is my sincere believe and philosophy that you learn most by by forcing your brain to do new and unfamiliar things, by mental effort and sweat. So have at it, you've nothing to lose.
You can count the the mouse clicks in this way. By using an if-else or switch case you can display the images.
public class ButtonStart extends Frame {
private int mouseclicked = 0;
TextField objTextField;
public static void main(String args[]) {
ButtonStart BS = new ButtonStart();
}
public ButtonStart() {
Frame objFrame;
Button objButton;
TextField objTextField;
objFrame = new Frame("Clicking Buttons");
objButton = new Button("Click me!");
objTextField = new TextField("0");
objFrame.addMouseListener(new MyMouseListener());
objFrame.add(objButton);
objFrame.add(objTextField);
objFrame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
}
public class MyMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent me) {
int mouseclicked = me.getClickCount();
objTextField.setText("Mouse clicked this many times:"
+ mouseclicked);
}
}
}

Hide a button from Layout in Java Swing

I am trying something very basic:
I have a list of 5 buttons. They are in a FlowLayout and the general idea should be that once I click one it should disappear and the others should reorder themselves accordingly.
Now, if I call setVisible(false) the button becomes invisible, but it still occupies it's space in the Layoutmanager.
Is there any way to keep the Button in the JPanel while hiding it so it doesn't get picked up by Layout?
Update:: Thanks for all the answers, the problem with removing the buttons is that the order is important. The problem I was trying to solve was a find as you type szenario where a very long list of buttons gets filtered down to only the ones matching the characters entered so users can easily click them. Since users can delete characters from the search field ordering is important and buttons have to pop back in once they match again.
Works fine for me.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FlowLayoutInvisible extends JFrame
implements ActionListener
{
JPanel north;
int i;
public FlowLayoutInvisible()
{
north = new JPanel();
for (int i = 0; i < 5; i++)
{
JButton button = new JButton("North - " + i);
button.addActionListener(this);
north.add(button);
}
getContentPane().add(north, BorderLayout.NORTH);
}
public void actionPerformed(ActionEvent e)
{
Component c = (Component)e.getSource();
c.setVisible(false);
((JPanel)c.getParent()).revalidate();
}
public static void main(String[] args)
{
FlowLayoutInvisible frame = new FlowLayoutInvisible();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
If you need more help post your SSCCE.
Update: I don't know if the revalidate() is required. I seemed to have a problem once but now I can't duplicate the problem.
Just remove it:
panel.remove( button );
What's wrong with this option?
Layout managers are thought precisely to avoid having the "user" to make tricks in order to have each component it the right place ( although it seems to provoke the opposite effect )
Removing the button from the panel will have the effect of laying out again all the remaining components. That's why it's name is "Layout manager" it manages to layout the components for you.
I see two possibilities:
Write your own layout manager that listens for changes to its children's visible property - shouldn't be too hard, you can probably subclass FlowLayout to do it.
actually remove the clicked-button from the panel and, if necessary, re-add it later.
You could override each button's getPreferredSize() methods (and possibly getMinimumSize() as well to return 0,0 when the component is invisible; and you need to call, I think, invalidate() (or revalidate or validate, I can never keep them straight) on the container.

Categories