Views
8 months ago

tornadofx-guide

EventBus EventBus An

EventBus EventBus An EventBus is a versatile tool with a multitude of use cases. Depending on your coding style and preferences, you might want to reduce coupling between controllers and views by passing messages instead of having hard references to each other. The TornadoFX event bus can make sure that the messages are received on the appropriate thread, without having to do that concurrency house-keeping manually. People use event buses for many different use cases. TornadoFX does not dictate when or how you should use them, but we want to show you some of the advantages it can provide to you. Structure of the EventBus As with any typical event bus implementation, you can fire events as well as subscribe and unsubscribe to events on the bus. You create an event by extending the FXEvent class. In some cases, an event can be just a signal to some other component to trigger something to happen. In other cases, the event can contain data which will be broadcast to the subscribers of this event. Let us look at a couple of event definitions and how to use them. Picture a UI where the user can click a Button to refresh a list of customers. The View knows nothing of where the data is coming from or how it is produced, but it subscribes to the data events and uses the data once it arrives. Let us create two event classes for this use case. First we define an event signal type to notify any listeners that we want some customer data: import tornadofx.EventBus.RunOn.* object CustomerListRequest : FXEvent(BackgroundThread) This event object is an application-wide object . Because it will never need to contain data, it will simply be broadcast to say that we want the customer list. The RunOn property is set to BackgroundThread , to signal that the receiver of this event should operate off of the JavaFX Application Thread. That means it will be given a background thread by default, so that it can do heavy work without blocking the UI. In the example above, we have added a static import for the RunOn enum, so that we just write BackgroundThread instead of EventBus.RunOn.BackgroundThread . Your IDE will help you to make this import so your code looks cleaner. 218

EventBus A button in the UI can fire this event by using the fire function: button("Load customers").action { } fire(CustomerListRequest) A CustomerController might listen for this event, and load the customer list on demand before it fires an event with the actual customer data. First we need to define an event that can contain the customer list: class CustomerListEvent(val customers: List) : FXEvent() This event is a class rather than an object , as it will contain actual data and vary. Also, it did not specify another value for the RunOn property, so this event will be emitted on the JavaFX Application Thread. A controller can now subscribe to our request for data and emit that data once it has it: class CustomerController : Controller() { init { subscribe { val customers = loadCustomers() fire(CustomerListEvent(customers)) } } } fun loadCustomers(): List = db.selectAllCustomers() Back in our UI, we can listen to this event inside the customer table definition: tableview { column("Name", Customer::nameProperty) column("Age", Customer::ageProperty) } subscribe { event -> } items.setAll(event.customers) We tell the event bus that we are interested in CustomerListEvent s, and once we have such an event we extract the customers from the event and set them into the items property of the TableView . 219

GUIDE
Guide
GUIDE
GUIDE
GUIDE
Guide
Guide
Guide
Guide
GUIDE