JavaFX how to update label text value every time? - javafx-8

I am using IntellijIDEA. I have ui.fxml,Controller.java and GUI.java. Here is code:
ui.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-1.0" minWidth="-1.0" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="sample.Controller">
<children>
<Button fx:id="exitBtn" cancelButton="true" layoutX="530.0" layoutY="366.0" mnemonicParsing="false" text="Exit" />
<Button fx:id="stopBtn" layoutX="460.0" layoutY="367.0" mnemonicParsing="false" text="Stop" />
<Button fx:id="startBtn" layoutX="387.0" layoutY="368.0" mnemonicParsing="false" text="Start" />
<Label fx:id="threadsLabel" layoutX="19.0" layoutY="23.0" prefWidth="45.0" text="Threads" />
<Label fx:id="threadsValue" layoutX="160.0" layoutY="26.0" prefWidth="45.0" text="0" />
<Label fx:id="smLabel" layoutX="19.0" layoutY="42.0" prefWidth="108.0" text="submit_sm sended" />
<Label fx:id="smValue" layoutX="160.0" layoutY="42.0" prefWidth="45.0" text="0" />
<Label fx:id="deliverLabel" layoutX="19.0" layoutY="61.0" prefWidth="115.0" text="deliver_sm received" />
<Label fx:id="deliverValue" layoutX="160.0" layoutY="61.0" prefWidth="45.0" text="0" />
<Label fx:id="tpsLabel" layoutX="19.0" layoutY="77.0" prefWidth="78.0" text="Current TPS" />
<Label fx:id="tpsValue" layoutX="160.0" layoutY="77.0" prefWidth="45.0" text="0" />
<Slider fx:id="speed" layoutX="213.0" layoutY="28.0" max="1000.0" min="10.0" prefWidth="317.0" showTickLabels="true" showTickMarks="false" />
</children>
</AnchorPane>
GUI.java
public class GUI extends Application {
public Logger log = Main.getLogger("log");
#Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader();
Parent root = loader.load(getClass().getResource("ui.fxml"));
primaryStage.setTitle("ESME Emulator");
Scene mainScene = new Scene(root, 600, 400);
primaryStage.setScene(mainScene);
primaryStage.show();
}
public void show(String[] args) {
launch(args);
}
}
Controller.java
public class Controller implements Initializable {
public Logger log=Main.getLogger("log");
#FXML
public ResourceBundle resources;
#FXML
public URL location;
#FXML
public Label deliverLabel;
#FXML
public Label deliverValue;
#FXML
public Button exitBtn;
#FXML
public Label smLabel;
#FXML
public Label smValue;
#FXML
public Slider speed;
#FXML
public Button startBtn;
#FXML
public Button stopBtn;
#FXML
public Label threadsLabel;
#FXML
public Label threadsValue;
#FXML
public Label tpsLabel;
#FXML
public Label tpsValue;
public Sample sample;
public Controller()
{
this.sample=new Sample(this);
}
public void initialize(URL location, ResourceBundle resources) {
stopBtn.setDisable(true);
startBtn.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
try {
Main.startEmulation();
startBtn.setDisable(true);
stopBtn.setDisable(false);
}catch(Exception e)
{
log.error("Exception while \"Start\" button click event: "+e.getMessage());
}
}
});
stopBtn.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
try {
Main.stopEmulation();
startBtn.setDisable(false);
stopBtn.setDisable(true);
}catch(Exception e)
{
log.error("Exception while \"Stop\" button click event: "+e.getMessage());
}
}
});
exitBtn.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
try {
Main.stopEmulation();
System.exit(0);
}catch(Exception e)
{
log.error("Exception while \"Exit\" button click event: "+e.getMessage());
}
}
});
}
}
and i have another java class which provides a while endless loop, and i need every iteration the threadsValue to be changed via thredsValue.setText("some text"), how can i do this?
p.s.excuse me for my english...
I did this, and still no result, whats wrong?
UpdateTask updTask = new UpdateTask();
Label.textProperty().bind(updTask.valueProperty());
Thread changes = new Thread(updTask);
changes.setDaemon(true);
changes.setName("UPDATE");
changes.start();
class UpdateTask extends Task<String> {
#Override
protected String call() throws Exception {
while(isRunning()) {
updateValue(Integer.toString(Main.getThreadsCount()));
}
return null;
}
}

Related

How can I pass object while navigating? [duplicate]

This question already has an answer here:
How pass parameter when navigate to another page (Shell)
(1 answer)
Closed 4 months ago.
I have main page on which I have collection view. I want to navigate to next page after I click submit button .I am able to navigate to the next page but I also want total list of items which I have in my collection how can I achieve that?
I don't know the detail of your code, but you can try to pass the total list of items as the parameter of the next page.(suppose it's name is SecondPage)
You can refer to the following code:
MainPage.cs
public partial class MainPage : ContentPage
{
MyViewModel myViewModel;
public MainPage()
      {
            InitializeComponent();
myViewModel = new MyViewModel();
BindingContext = myViewModel;
}
      private void mCollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
      {
string previous = (e.PreviousSelection.FirstOrDefault() as MyModel)?.Name;
string current = (e.CurrentSelection.FirstOrDefault() as MyModel)?.Name;
}
private async void Button_Clicked(object sender, EventArgs e)
{
// here we can pass the data we need.
var secondPage = new SecondPage(myViewModel.Data);
await Navigation.PushAsync(secondPage);
}
}
MainPage.xaml.cs
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiCollectionApp.MainPage"
xmlns:local="clr-namespace:MauiCollectionApp"
x:Name="myPage"
>
<VerticalStackLayout>
<CollectionView ItemsSource="{ Binding Data}" x:Name="mCollectionView"
SelectionChanged="mCollectionView_SelectionChanged"
SelectionMode="Single"
>
<CollectionView.ItemTemplate>
<DataTemplate>
<HorizontalStackLayout Margin="3" >
<Label Text="{Binding Name}" BackgroundColor="Gray"/>
<Label Text="{Binding Car.Make}" Margin="5,0,5,0" />
<Button Text="delete" Margin="10,0,0,0"
BackgroundColor="Red"
Command="{Binding Path= BindingContext.RemoveEquipmentCommand,Source={Reference mCollectionView }}" CommandParameter="{Binding .}"
/>
</HorizontalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Button Text="submit" Clicked="Button_Clicked" Margin="10"/>
</VerticalStackLayout>
</ContentPage>
MyViewModel.cs
public class MyViewModel: INotifyPropertyChanged
{
public ObservableCollection<MyModel> Data { get; set; }
public ICommand RemoveEquipmentCommand => new Command<MyModel>(ReMoveItem);
private void ReMoveItem(MyModel obj)
{
System.Diagnostics.Debug.WriteLine(" the selected item's name is: " + obj.Name );
Data.Remove(obj);
}
public MyViewModel() {
Data = new ObservableCollection<MyModel>();
Data.Add(new MyModel { Name ="model_1", Car= new Vehicle {Make="Make1" } });
Data.Add(new MyModel { Name = "model_2", Car = new Vehicle { Make = "Make2" } });
Data.Add(new MyModel { Name = "model_3", Car = new Vehicle { Make = "Make3" } });
Data.Add(new MyModel { Name = "model_4", Car = new Vehicle { Make = "Make4" } });
}
bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Object.Equals(storage, value))
return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
SecondPage.cs
public partial class SecondPage : ContentPage
{
public ObservableCollection<MyModel> Items { get; set; }
public SecondPage(ObservableCollection<MyModel> data )
      { // we can get the passed data here
            InitializeComponent();
            this.Items = data;
      }
}

Popup in .Net Maui application

I use Xamarin community toolkit mauicompat to implement popup for .net maui but when I call to open the popup, it had an error like the image below
and my code here:
public partial class HomePage : ContentPage
{
public HomePage()
{
InitializeComponent();
}
private void BtPop_Clicked(object sender, System.EventArgs e)
{
Navigation.ShowPopup(new PopupServicess()
{
IsLightDismissEnabled = true,
});
}
private void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
}
here my xaml file:
<xct:Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
Size="300,300"
x:Class="NailsApp.Views.PopupServicess">
<StackLayout>
<Label Text="Hello from Popup!"/>
</StackLayout>
</xct:Popup>
public partial class PopupServicess : Popup
{
public PopupServicess()
{
}
}

data is not getting in viewmodel on Icommand button click

I have a form for capturing data from user.
<StackLayout Spacing="10" Margin="20,10,20,0">
<Label Text="Job Name"></Label>
<Entry BackgroundColor="White" x:Name="JobName" Text="{Binding SelectedJob.Name,Mode=TwoWay}"/>
<Label Text="Goal"></Label>
<Entry BackgroundColor="White" x:Name="Goal" Text="{Binding SelectedJob.Goal,Mode=TwoWay}"/>
<Grid ColumnSpacing="8" HorizontalOptions="FillAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="Save" Command="{Binding SubmitCommand}" BackgroundColor="#078fc1" Grid.Column="0" HorizontalOptions="FillAndExpand"/>
<Button Text="Reset" BackgroundColor="#078fc1" Grid.Column="1" HorizontalOptions="FillAndExpand"/>
</Grid>
</StackLayout>
on button click i want to bind data to SelectedJob object.
this is my ViewModel
public class JobViewModel: INotifyPropertyChanged
{
public JobViewModel()
{
SubmitCommand = new Command(OnSubmitAsync);
}
private JobDTO selectedob { get; set; }
public JobDTO SelectedJob
{
get { return selectedob; }
set
{
selectedob = value;
OnPropertyChanged(nameof(SelectedJob));
}
}
public ICommand SubmitCommand { protected set; get; }
public async void OnSubmitAsync()
{
await.jobservice.postjob()
}
}
and this is my model
public class JobDTO:INotifyPropertyChanged
{
private string name { get; set; }
public string Name
{ get { return name;}
set
{
name = value;
OnPropertyChanged(nameof(Name));
}
}
private string goal;
public string Goal
{
get { return goal; }
set
{
goal = value;
OnPropertyChanged(nameof(Goal));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
on button click i am getting SelectedJob as null,eventhough i made my class as JobDTO:INotifyPropertyChanged.can any one help me what i am doing here wrong.
I changed the code of ViewModel and model.
There is GIF of demo based on your code.
ViewModel of JobViewModel
If you want to used get/set method, one attribute corresponds to one get/set method, I also add OnPropertyChangedmethod.
public class JobViewModel : INotifyPropertyChanged
{
public JobViewModel()
{
SubmitCommand = new Command(OnSubmitAsync);
}
private JobDTO selectedob=new JobDTO();
public JobDTO SelectedJob
{
get { return selectedob; }
set
{
selectedob = value;
OnPropertyChanged("SelectedJob");
}
}
public ICommand SubmitCommand { protected set; get; }
public event PropertyChangedEventHandler PropertyChanged;
public async void OnSubmitAsync()
{
// i donnot know what is your aim of this part, i just pop up a alert that contains Name and Goal from Entry.
await Application.Current.MainPage.DisplayAlert("Alert", "Name: "+SelectedJob.Name+"\n"+ "Goal: "+ SelectedJob.Goal , "Ok");
}
protected virtual void OnPropertyChanged(string propertyName)
{
var changed = PropertyChanged;
if (changed != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Model of JobDTO, The changed place is same with ViewModel
public class JobDTO: INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged("Name");
}
}
private string goal;
public string Goal
{
get { return goal; }
set
{
goal = value;
OnPropertyChanged("Goal");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
var changed = PropertyChanged;
if (changed != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
MainPage.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DateBoundingDemo"
x:Class="DateBoundingDemo.MainPage">
<StackLayout Spacing="10" Margin="20,10,20,0">
<Label Text="Job Name"></Label>
<Entry BackgroundColor="White" x:Name="JobName" Text="{Binding SelectedJob.Name,Mode=TwoWay}"/>
<Label Text="Goal"></Label>
<Entry BackgroundColor="White" x:Name="Goal" Text="{Binding SelectedJob.Goal,Mode=TwoWay}"/>
<Grid ColumnSpacing="8" HorizontalOptions="FillAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="Save" Command="{Binding SubmitCommand}" BackgroundColor="#078fc1" Grid.Column="0" HorizontalOptions="FillAndExpand"/>
<Button Text="Reset" BackgroundColor="#078fc1" Grid.Column="1" HorizontalOptions="FillAndExpand"/>
</Grid>
</StackLayout>
</ContentPage>
MainPage.xaml.cs
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext =new JobViewModel();
}
}

Prism Button click command

Im try to open Drawer menu (Syncfusion control) via Behaviors command
Xaml
<Button x:Name="hamburgerButton"
HeightRequest="50" WidthRequest="50"
HorizontalOptions="Start" FontSize="20"
BackgroundColor="#1aa1d6" >
<Button.Behaviors>
<b:EventToCommandBehavior EventName="Clicked"
Command="{Binding HamburgerButton}" />
</Button.Behaviors>
VM cs
public DelegateCommand HamburgerButton { get; private set; }
public QuickPartViewModel(INavigationService navigationService)
{
HamburgerButton = new DelegateCommand(HamburgerButton_Clicked);
}
public void HamburgerButton_Clicked(object sender, EventArgs e)
{
navigationDrawer.ToggleDrawer();
}
If HamburgerButton_Clicked(object sender, EventArgs e) with arguments then i have error -// Argumment: cannot convert from 'method group' to Action
if I'm remove Argumments it does't work
You're overthinking things. Just bind the command to the button.
in the page:
<Button Command="{Binding HamburgerCommand}" />
in the view model:
public QuickPartViewModel()
{
HamburgerCommand = new DelegateCommand(OnHamburger);
}
public DelegateCommand HamburgerCommand { get; }
private void OnHamburger()
{
navigationDrawer.ToggleDrawer();
}
Give the docs a try...

Multiple FXML variables to 1 controller handle

How can I make a handle that applies to each of the buttons, so I don't have to make a near-identical handle for each button?
So I have a FXML file with 9 contacts, each looks like this:
<Button fx:id="id1" mnemonicParsing="false" onAction="#handleContactEmailButtonAction" prefHeight="60.0" prefWidth="380.0" style="-fx-background-color: white;">
<graphic>
<VBox style="-fx-background-color: white; -fx-border-color: white;">
<children>
<Label prefHeight="30.0" prefWidth="334.0" text="Jane Doe" />
<Label prefHeight="17.0" prefWidth="349.0" text="jdoe#britishschool.sch.ae" textAlignment="CENTER" />
</children>
</VBox>
</graphic>
</Button>
And this is the controller:
#FXML
private Button id1;
#FXML
private Button id2;
#FXML
private Button id3;
#FXML
private Button id4;
#FXML
private Button id5;
#FXML
private Button id6;
#FXML
private Button id7;
#FXML
private Button id8;
#FXML
private Button id9;
#FXML
protected void handleContactEmailButtonAction(ActionEvent event) {
try {
Desktop desktop = Desktop.getDesktop();
String message = "mailto:"+emailvariable+"?subject=Music%20Bookings";
URI uri = URI.create(message);
desktop.mail(uri);
} catch (Exception e) {
e.printStackTrace();
}
}
So if button with fx:id="id1" is clicked, then email variable changes to the email in the relevant label, and all with one controller?
Any and all help is appreciated, thank you!
Create a Map where you can get the button from event source like:
#FXML
private Button id1;
#FXML
private Button id2;
#FXML
private Button id3;
#FXML
private Button id4;
#FXML
private Button id5;
#FXML
private Button id6;
#FXML
private Button id7;
#FXML
private Button id8;
#FXML
private Button id9;
private Map<Button, String> emailVariables;
#Override
public void initialize(URL location, ResourceBundle resources)
{
emailVariables = new HashMap<Button, String>();
emailVariables.put(id1, "id1#example.com");
emailVariables.put(id2, "id2#example.com");
emailVariables.put(id3, "id3#example.com");
emailVariables.put(id4, "id4#example.com");
emailVariables.put(id5, "id5#example.com");
emailVariables.put(id6, "id6#example.com");
emailVariables.put(id7, "id7#example.com");
emailVariables.put(id8, "id8#example.com");
emailVariables.put(id9, "i91#example.com");
}
#FXML
protected void handleContactEmailButtonAction(ActionEvent event)
{
try
{
Desktop desktop = Desktop.getDesktop();
String message = "mailto:" + emailvariables.get((Button) event.getSource()) + "?subject=Music%20Bookings";
URI uri = URI.create(message);
desktop.mail(uri);
}
catch (Exception e)
{
e.printStackTrace();
}
}
Code is not tested.
Consider creating a custom component:
package application;
import java.awt.Desktop;
import java.io.IOException;
import java.net.URI;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
public class EmailButton extends Button {
#FXML
private Label nameLabel ;
#FXML
private Label addressLabel ;
private final StringProperty name = new SimpleStringProperty();
private final StringProperty emailAddress = new SimpleStringProperty();
public EmailButton() throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("emailButton.fxml"));
loader.setRoot(this);
loader.setController(this);
loader.load();
}
public void initialize() {
nameLabel.textProperty().bind(name);
addressLabel.textProperty().bind(emailAddress);
}
#FXML
private void sendEmail() {
try {
Desktop desktop = Desktop.getDesktop();
String message = "mailto:"+getEmailAddress()+"?subject=Music%20Bookings";
URI uri = URI.create(message);
desktop.mail(uri);
} catch (Exception e) {
e.printStackTrace();
}
}
public StringProperty nameProperty() {
return name ;
}
public final String getName() {
return nameProperty().get();
}
public final void setName(String name) {
nameProperty().set(name);
}
public StringProperty emailAddressProperty() {
return emailAddress ;
}
public final String getEmailAddress() {
return emailAddressProperty().get();
}
public final void setEmailAddress(String emailAddress) {
emailAddressProperty().set(emailAddress);
}
}
and emailButton.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<fx:root xmlns:fx="http://javafx.com/fxml/1" type="Button" mnemonicParsing="false" onAction="#sendEmail" prefHeight="60.0" prefWidth="380.0" style="-fx-background-color: white;">
<graphic>
<VBox style="-fx-background-color: white; -fx-border-color: white;">
<children>
<Label fx:id="nameLabel" prefHeight="30.0" prefWidth="334.0" />
<Label fx:id="addressLabel" prefHeight="17.0" prefWidth="349.0" textAlignment="CENTER" />
</children>
</VBox>
</graphic>
</fx:root>
Now in your main FXML you can just do:
<?import application.EmailButton?>
<!-- ... -->
<EmailButton name="Jane Doe" emailAddress="jdoe#britishschool.sch.ae"/>
<EmailButton name="..." emailAddress="..." />
<EmailButton name="..." emailAddress="..."/>
etc