For a few days I have been trying to create a JPanel, that comes flying in from the side. I found the Universal Tween Engine and also saw a few demos but for some reason I was never able to make it work in my own code. For the sake of simplicity let's just attempt to move a JPanel (containing an image in a JLabel) from (0,0) to (600,0) on a JFrame. This is what I've got so far and the closest I have ever gotten to actually moving things with this framework, all it does it make the JPanel jump to its destination within the first tick or so. It is supposed to be so simple but I must be missing something...
SlideTest.java - Creating the UI, initializing the Thread + Tween
public class SlideTest {
TweeningPane p;
public TweenManager tweenManager;
public static void main(String[] args) {
new SlideTest();
}
public SlideTest() {
try {
setupGUI();
} catch (IOException e) {
e.printStackTrace();
}
tweenManager = new TweenManager();
AnimationThread aniThread = new AnimationThread();
aniThread.setManager(tweenManager);
aniThread.start();
Tween.to(p, 1, 10.0f).target(600).ease(Quad.OUT).start(tweenManager);
}
public void setupGUI() throws IOException {
JFrame f = new JFrame();
f.setSize(800, 600);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
p = new TweeningPane();
JLabel l = new JLabel(new ImageIcon("E:/Pictures/Stream/aK6IX4V.png"));
f.setLayout(null);
p.add(l);
p.setBounds(0, 0, 300, 300);
f.add(p);
f.setVisible(true);
}
}
AnimationThread.java - The Thread, that is supposed to keep my TweenManager updated as much/often as possible
public class AnimationThread extends Thread {
TweenManager tm;
public void setManager(TweenManager tweenmanager) {
this.tm = tweenmanager;
}
public void run() {
while (true) {
//System.out.println("MyThread running");
tm.update(MAX_PRIORITY);
try {
sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
TweeningPane.java - My Object(JPanel), I want to move across the JPanel
public class TweeningPane extends JPanel implements TweenAccessor<JPanel> {
private static final long serialVersionUID = 1L;
#Override
public int getValues(JPanel arg0, int arg1, float[] arg2) {
return (int) arg0.getBounds().getX();
}
#Override
public void setValues(JPanel arg0, int arg1, float[] arg2) {
arg0.setBounds((int) arg2[0], 0, 300, 300);
}
}
I have finally figured it out. I was simply using the framework in a wrong way as I expected. I'm not sure whether all these steps were needed but this is what I went through in order to make it work: (for future reference)
I had to register my accessor to the engine:
Tween.registerAccessor(TweeningPane.class, new TweeningPane());
And the thread itself now looks like this; I had to give the manager's update method the elapsed time as a parameter.
public void run() {
long ms1 = System.currentTimeMillis();
while (true) {
//System.out.println("MyThread running");
tm.update((System.currentTimeMillis() - ms1) / 1000f);
try {
Thread.sleep(40);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Related
I need to call an API every 30 seconds and need to refresh the grid with updated data. I using Server push, but I can't find the optimal solution in my case. Below is my UI code
#Route(value = UserNavigation.ROUTE)
#PreserveOnRefresh
#org.springframework.stereotype.Component
public class UserNavigation extends AppLayout {
CCUIConfig config;
#Autowired
public UserNavigation( CCUIConfig config) {
this.config = config;
addToDrawer(createAccordianMenu());
}
private Component createAccordianMenu() {
VerticalLayout scrollableLayout = new VerticalLayout();
Div kioskMonitor_div = new Div(kiosksMonitorLabel);
kioskMonitor_div.addClickListener(event -> {
try {
setContent(new Monitor(config).getDashboard());
} catch (Exception e) {
e.printStackTrace();
}
});
scrollableLayout.add(kioskMonitor_div);
return scrollableLayout;
}
}
#Push
#Route
public class Monitor extends VerticalLayout{
CCUIConfig config;
Grid<Model> grid = new Grid<>();
private FeederThread thread;
public Monitor(CCUIConfig config) {
this.config = config;
}
#Override
protected void onAttach(AttachEvent attachEvent) {
// Start the data feed thread
super.onAttach(attachEvent);
thread = new FeederThread(attachEvent.getUI(),grid);
thread.start();
}
#Override
protected void onDetach(DetachEvent detachEvent) {
thread.interrupt();
thread = null;
}
public Component getDashboard() throws IOException{
String updateddate =null;
VerticalLayout dashboardview = new VerticalLayout();
Grid.Column<Model> idColumn = grid.addColumn(Model::getid)
.setHeader(ID);
Grid.Column<Model> nameColumn = grid.addColumn(Model::getName)
.setHeader(Name);
Grid.Column<Model> memoryColumn = grid.addColumn(Model::getRefreshTime)
.setHeader(Refresh time"));
dashboardview.add(grid);
return dashboardview;
}
}
class FeederThread extends Thread {
private final com.vaadin.flow.component.UI ui;
private final Grid<Model> grid;
private final CCUIConfig config;
private int count = 30;
public FeederThread(com.vaadin.flow.component.UI ui,Grid<Model> grid) {
this.config = new CCUIConfig();
this.ui = ui;
this.grid= grid;
}
#Override
public void run() {
while (count>0){
try {
Thread.sleep(1000);
ui.access(()-> {
System.out.println("Thread Entry ");
try {
StringBuilder jsongrid = HttpClientGetRequestClient.executeUrlGet(config.getRefreshAPI());
ObjectMapper mapper = new ObjectMapper();
List<Model> userlist = new ArrayList<Model>();
String date="";
if(jsongrid!=null)
{
ModelWrapper eh = mapper.readValue(jsongrid.toString(), ModelWrapper.class);
userlist = eh.getMetricsData();
}
if(userlist != null)
{
grid.setItems(userlist);
grid.getDataProvider().refreshAll();
}
}catch(JSONException |JsonProcessingException e) {
e.printStackTrace();
}
});
count--;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
UserNavigation is the page that loads after user login, it contains a sidebar with multiple options(or functionalities). One of the functionality is the Monitor screen.
Monitor is the page with a grid where we need to refresh it in 30 seconds.
FeederThread is the thread class that calls an API and update the data in the grid asynchronously.
As from the above code, what happens is like
onAttach(AttachEvent attachEvent)
is not getting executed so the grid is not getting displayed on the page, we use vaadin 14, any help will be appreciated.
I'm new to JavaFX.
I'm building a GUI for a project of mine, and I have a problem with it -
it seems that once I show my UI it stops updating.
In my case, it supposed to update a fill colour for a circle but it does not.
I tried to move the line:
someCircleId.setFill(color));
to be above the line:
Main.stage.show();
in the initialize function in my code and it did change the color of
the certain circle.
public class UIController implements Initializable {
public UIController() {
fillMap();
}
#Override
public void initialize(URL location, ResourceBundle resources) {
Main.stage.show();
}
#FXML
public void pressExitButton() {
Main.dropDBSchema();
System.exit(0);
}
public void changeCircleColor(String circleKey, Color color) {
Platform.runLater(
() -> {
Circle circle = this.circles.get(circleKey);
PauseTransition delay = new PauseTransition(Duration.seconds(10));
delay.setOnFinished(event -> circle.setFill(color));
delay.play();
}
);
}
}
And this is the class that uses these functions:
public class MonitoringLogicImpl implements MonitoringLogic {
public void updateUI(UUID flowUUID, String sender, String receiver, DATA_STATUS status){
String key = flowUUID.toString()+"_"+sender+"_"+receiver;
Color color = this.uiController.getColorAccordingToStatus(status);
this.uiController.changeCircleColor(key, color);
}
}
This is the FXML initialization :
public void start(Stage stage){
this.stage = stage;
FXMLLoader loader = new FXMLLoader();
try {
loader.setLocation(getClass().getResource("/UserInterface.fxml"));
this.root = loader.load();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
stage.setTitle("Troubleshooting project");
stage.setScene(new Scene(root, 900, 700));
stage.show();
}
I created my UI using Scene-Builder tool.
I have a platformer class that creates a window and spawns platforms and a "character". It uses another class platform to make platforms. The character is supposed to jump up and land on the platforms. I use the getBounds and getTopY functions for collision detection but they only work for the first platform. How can i get them to work for multiple platforms?
public class Platformer extends JPanel {
Platform platform = new Platform(this);
Character character = new Character(this);
public Platformer() {
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
character.keyTyped(e);
}
#Override
public void keyReleased(KeyEvent e) {
character.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
character.keyPressed(e);
}
});
setFocusable(true);
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
platform.Location(150,200);
platform.paint(g2d);
platform.Location(200,120);
platform.paint(g2d);
character.paint(g2d);
}
private void move(){
character.move();
}
public static void main(String args[]){
JFrame frame = new JFrame("Mini Tennis");
//create new game
Platformer platformer = new Platformer();
//add game
frame.add(platformer);
//size
frame.setSize(400, 400);
frame.setVisible(true);
//set close condition
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true) {
platformer.move();
platformer.repaint();
try {
Thread.sleep(10);//sleep for 10 sec
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
public class Platform {
private static final int Height = 10;
private static final int Width = 60;
int x;
int Y;
private Platformer platformer;
public Platform(Platformer platformer) {
this.platformer = platformer;
}
public void Location(int xin, int yin) {
x = xin;
Y = yin;
}
public void paint(Graphics2D g) {
g.fillRect(x, Y, Width, Height);
}
public Rectangle getBounds() {
return new Rectangle(x, Y, Width, Height);
}
public int getTopPlat() {
return Y;
}
}
Actually you have only one platform. And you draw this platform twice in different places (paint function in Platformer):
platform.Location(150,200);
platform.paint(g2d);
platform.Location(200,120);
platform.paint(g2d);
Therefore I suppose you handle only one platform (with coordinates 200 and 120). You must keep all of your platforms and handle each of them separately.
I'm developing an android app that requires to make UI changes according to a background thread processing results, I tried the following code at first:
Thread run_time = new Thread (){
public void run(){
ConnectToServer connect = new ConnectToServer(null);
while(true){
String server_response = connect.getServerResponse();
if(!server_response.equals(null)){
setResponse(server_response);
response_received();
}
}
}
};
run_time.start();
but my App crashes because i tried to make a UI changes from that background thread, then I tried that way:
runOnUiThread(new Runnable() {
public void run(){
ConnectToServer connect = new ConnectToServer(null);
while(true){
String server_response = connect.getServerResponse();
if(!server_response.equals(null)){
setResponse(server_response);
response_received();
}
}
}
});
but i got that exception:
01-29 16:42:17.045: ERROR/AndroidRuntime(605): android.os.NetworkOnMainThreadException
01-29 16:42:17.045: ERROR/AndroidRuntime(605): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1084)
01-29 16:42:17.045: ERROR/AndroidRuntime(605): at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:151)
01-29 16:42:17.045: ERROR/AndroidRuntime(605): at libcore.io.IoBridge.recvfrom(IoBridge.java:503)
01-29 16:42:17.045: ERROR/AndroidRuntime(605): at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
01-29 16:42:17.045: ERROR/AndroidRuntime(605): at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
and after search i found that I must run the code as AsyncTask to avoid these problems, but when attempting to use it i found that it's must be used with small tasks only not like a thread that runs in the background all the run_time.
So, what's the best day to run a thread or a task in the background in whole the run_time and also reflect it's changes to the UI.
EDIT:
For Long running network work you have a few options.
First and formost check the android docs on this topic:
http://developer.android.com/training/basics/network-ops/index.html
Next, I generally use Services for this type of thing:
https://developer.android.com/guide/components/services.html
I will point you at the vogella tutorial for this as well:
http://www.vogella.com/tutorials/AndroidServices/article.html
For communication from threads/asynctasks/services to the UI use Handlers:
Use Handlers:
static public class MyThread extends Thread {
#Override
public void run() {
try {
// Simulate a slow network
try {
new Thread().sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
downloadBitmap = downloadBitmap("http://www.devoxx.com/download/attachments/4751369/DV11");
// Updates the user interface
handler.sendEmptyMessage(0);
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
// cal uiMethods here...
imageView.setImageBitmap(downloadBitmap);
// dialog.dismiss();
}
};
Taken from this tutorial:
http://www.vogella.com/tutorials/AndroidBackgroundProcessing/article.html
You can make this more interesting by defining constant_codes which corespond to the desired action:
private int DO_THIS = 0x0;
private int DO_THAT = 0x1;
// in your UI:
public void handleMessage(Message msg) {
// cal uiMethods here...
switch(msg.what()){
case(DO_THIS):
// do stuff
break;
case(DO_THAT):
// do other stuff
break;
}
}
// in your thread:
Message m = handler.obtainMessage(DO_THIS);
handler.sendMessage(m);
If the thread code (asynch task, service etc...) is separate from the UI you can use Broadcasts to pass the data between the two and then use Handlers from there to act on the UI thread.
you need to use handlers
here is documntation: https://developer.android.com/training/multiple-threads/communicate-ui.html
Use this code - it may contain compile time error you have to do it correct
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Connect connect = new Connect();
connect.execute();
}
class Connect extends AsyncTask<Void, String, Void>
{
#Override
protected Void doInBackground(Void... params)
{
ConnectToServer connect = new ConnectToServer(null);
while(true)
{
String server_response = connect.getServerResponse();
if(!server_response.equals(null))
{
publishProgress(server_response);
//setResponse(server_response);
response_received();
}
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
setResponse(values[0]);
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
}
You need "handlers" along with "loopers" for optimization
Example:
public void myMethod(){
Thread background = new Thread(new Runnable(){
#Override
public void run(){
Looper.prepare();
//Do your server process here
Runnable r=new Runnable() {
#Override
public void run() {
//update your UI from here
}
};
handler.post(r);
Looper.loop();
}
});
background.start();
}
And of course this is without using AsyncTask
I have designed a component for J2Me, and here is the paint method:
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
class Component {
...
public void paint(Graphics g) {
if (background != null)
g.drawImage(image, bounds.getLocation().x, bounds.getLocation().y, 0);
}
...
}
I want to paint this component on a J2Se application, I tried to paint the component onto a J2Me Image and extracted the int[] into an InputStream, and create a new image on the J2Se platform, with this object:
public class ComponentStreamer {
private Component component;
private Image j2Me_Image;
public void setComponent(Component component) {
this.component = component;
}
public InputStream getInputStream() throws IOException {
if(component==null)
return null;
//THIS LINE THROWS THE EXCEPTION
j2Me_Image=Image.createImage(component.getSize().width, component.getSize().height);
component.paint(j2Me_Image.getGraphics());
return getImageInputStream(j2Me_Image);
}
}
I've tried the Object, but the commented line throws an exception:
Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: javax.microedition.lcdui.ImmutableImage.decodeImage([BII)V
at javax.microedition.lcdui.ImmutableImage.decodeImage(Native Method)
at javax.microedition.lcdui.ImmutableImage.getImageFromStream(Image.java:999)
at javax.microedition.lcdui.ImmutableImage.<init>(Image.java:955)
at javax.microedition.lcdui.Image.createImage(Image.java:554)
How can over come this error?
Thanks,
Adam.
Well,
That was a very long process of diving into the sources of the J2Me MIDP and CLDC, and the use of a package called Microemulator, here is some code to get anyone else started:
this starts an emulator, which then enables some of the J2Me features.
private void setUpEmulator() {
try {
// overrideJ2MeImagePackageLock();
Headless app = new Headless();
DeviceEntry defaultDevice = new DeviceEntry("Default device", null, DeviceImpl.DEFAULT_LOCATION, true, false);
Field field = app.getClass().getDeclaredField("emulator");
field.setAccessible(true);
Common emulator = (Common) field.get(app);
emulator.initParams(new ArrayList<String>(), defaultDevice, J2SEDevice.class);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Un-handled Exception");
}
}
Next we have few other nice objects to work with:
public class J2MeImageLayer extends ScalableLayer {
private static final long serialVersionUID = -4606125807092612043L;
public J2MeImageLayer() {
componentViewer.super();
}
#Override
public void repaint() {
J2SEMutableImage mutableImage = new J2SEMutableImage(page.getSize().width, page.getSize().height);
page.paint(mutableImage.getGraphics());
Graphics g = getImage().getGraphics();
g.drawImage(mutableImage.getImage(), 0, 0, DCP_Simulator.this);
}
public void addComponent(Component component) {
page.add(component);
}
public void setComponent(final Component component) {
page.removeAllElements();
final Container componentParent;
if ((componentParent = component.getParent()) != null)
component.setRemovedAction(new interfaces.Action() {
#Override
public void action() {
componentParent.add(component);
}
});
page.add(component);
}
}
and this is the highlight on how to do that.
Adam.