FXML controller class too large - coding-style

So I've been practising with JavaFX for a while now and while I love it, I find that my application is growing in size- especially in terms of the number of lines of codes for my FXML Controllers.
Right now a typical package for each scene in my application looks like this:
MyFXML.fxml
MyFXMLController.java
MyDataModel.java
For example, I have a form that takes in some information from textfields, comboboxes and radio buttons. When a button is pressed the form information is saved to a database and is also updated immediately in the tableview.
The tableview also allows deleting and updating of the information displayed.
With only a few components (approx. 10) I have a Controller class file that is about 550 lines long with about a 100 of it taken up by the injections (#FXML) and imports and growing!
My application would ideally have multiple of these different kinds of forms and a controller for each. The database queries are all different so it's not quote possible to abstract them out yet. Also, event listeners for the tableview generally require longer code in javafx than other components.
I just feel like there's a better approach to GUI building in javafx than what I'm doing and was wondering if there was some kind of reference I could look up?
I've read up on other stackoverflow answers on the Single Responsibility Principle. If the code below is any hint, my application simply creates a new staff member and allows updating the information. So I'm confused as to whether my class is too file or is this normal for GUI programming?
I'm not asking for coding help, I'm looking for recommendations on how I can improve GUI programming in javafx.
Thank you!
--
FWIW, here's what a sample controller file looks like
package myApp.staff;
//30 something lines of imports...
public class NewStaffMemberController implements Initializable {
//80 something lines of private variables and #FXML injections
public void setConn(Connection aConn) {
conn = aConn;
wrapGenderRadioButtons();
populateDates();
populateStaffTypeComboBox();
populateDepartmentComboBox();
populateStaffTable();
}
private void wrapGenderRadioButtons() {
//4 lines
}
private void populateDates() {
//25 lines
}
private void populateStaffTypeComboBox() {
//20 lines
}
private void populateDepartmentComboBox() {
//22 lines
}
private void populateStaffTable(){
//longest at 100 lines. This code also adds the event listener for the tableview- makes it quite long!
}
private void editSelectedTableRow(Staff selectedstaff){
//4 lines
}
#FXML
private void selectedRadioBtnAction() {
//1 lines
}
#FXML
private void handleYearComboBoxAction() {
//1 lines
}
#FXML
private void handleMonthComboBoxAction() {
//1 lines
}
#FXML
private void handleDayComboBoxAction() {
//1 lines
}
#FXML
private void staffTypeComboBoxAction() {
//1 lines
}
#FXML
private void departmentComboBoxAction() {
//1 lines
}
#FXML
private void btnGenerateStaffId() {
//36 lines
}
#FXML
private void btnSaveInformation(){
13 lines
}
private Boolean validateData() {
//43 lines
}
private void assignStaffId() {
//12 lines
}
private void insertIntoDatabase() {
//35 lines
}
private void updateDatabase(){
//35 lines
}
#Override
public void initialize(URL url, ResourceBundle rb) {
}
}

Well, I think you don't have choice to inject your fxml fields you need. But maybe if you have number of injections like that just in one controller, you should maybe do a better conception of your app, by doing sub controllers working each other together and don't have everything in just one controller. One view doesn't mean one controller. You can have one view and multiple controller with there own view

Related

What are the PdfPCellEvent equivalent in iText7?

I am trying to run some samples from whitepaper "digitalsignatures20130304 A White Paper by Bruno Lowagie" [page 54]. I could not find the iText7 equivalents for PdfPCellEvent, PdfContentByte.
Please guide me.
iText 7 is a not a clone of iText 5 with some refactored package or class names, it has a new architecture. Thus, there is not always a 1:1 corresponding class but there are other ways to achieve the same effect.
It helps to look at the ports of the samples by the iText people; on github you can find many samples from the whitepaper ported to iText 7 in the i7js-signatures project.
For example you mention page 54 of the Digital Signatures for PDF documents whitepaper. Considering the keywords you gave and the fact that there is but one example on that page, I assume you want to translate this method and helper class:
protected PdfPCell createSignatureFieldCell(PdfWriter writer, String name) {
PdfPCell cell = new PdfPCell();
cell.setMinimumHeight(50);
PdfFormField field = PdfFormField.createSignature(writer);
field.setFieldName(name);
field.setFlags(PdfAnnotation.FLAGS_PRINT);
cell.setCellEvent(new MySignatureFieldEvent(field));
return cell;
}
public class MySignatureFieldEvent implements PdfPCellEvent {
public PdfFormField field;
public MySignatureFieldEvent(PdfFormField field) {
this.field = field;
}
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].getPdfWriter();
field.setPage();
field.setWidget(position, PdfAnnotation.HIGHLIGHT_INVERT);
writer.addAnnotation(field);
}
}
You find the port hereof in the class C2_11_SignatureWorkflow:
protected Cell createSignatureFieldCell(String name) {
Cell cell = new Cell();
cell.setHeight(50);
cell.setNextRenderer(new SignatureFieldCellRenderer(cell, name));
return cell;
}
class SignatureFieldCellRenderer extends CellRenderer {
public String name;
public SignatureFieldCellRenderer(Cell modelElement, String name) {
super(modelElement);
this.name = name;
}
#Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
PdfFormField field = PdfFormField.createSignature(drawContext.getDocument(), getOccupiedAreaBBox());
field.setFieldName(name);
field.getWidgets().get(0).setHighlightMode(PdfAnnotation.HIGHLIGHT_INVERT);
field.getWidgets().get(0).setFlags(PdfAnnotation.PRINT);
PdfAcroForm.getAcroForm(drawContext.getDocument(), true).addField(field);
}
}
As you can see there are certain differences, in particular instead of an event a Renderer is used, and the field construction and positioning aren't separated anymore, they take place at the same location in the code.

#UIScope annotation not respected for spring view?

I am facing an issue with the Vaadin spring annotation #UIScope, defined as follows:
#SpringComponent
#SpringView(name = AdminView.VIEW_NAME)
#UIScope
public class AdminView extends NavigatingView {
...
}
The view is created every time the navigation is opening the view. I would expect that it is created only once, on first time access.
However, if I replace #UIScope with #Scope(UIScopeImpl.VAADIN_UI_SCOPE_NAME) then it works as expected. Did I miss something?
It's related to the order of the #SpringView and #UIScope annotations, as the tutorial and the older wiki page briefly suggest:
// Pay attention to the order of annotations
It's probably related to how and when the annotations are processed. I did not dig that deep into the Vaadin code, but as per the the #SpringView javadoc it puts the view into a view-scope by default. Furthermore, I don't think you require the #SpringComponent annotation because you're already using #SpringView to register it a spring component.
Annotation to be placed on View-classes that should be handled by the SpringViewProvider.
This annotation is also a stereotype annotation, so Spring will automatically detect the annotated classes. By default, this annotation also puts the view into the view scope. You can override this by using another scope annotation, such as the UI scope, on your view class. However, the singleton scope will not work!
In the sample below, you'll find 2 views, the first one with the annotations in the correct order, and the second one with them swapped:
#SpringUI
#SpringViewDisplay
public class MyVaadinUI extends UI implements ViewDisplay {
/* UI */
private Panel springViewDisplay;
#Override
protected void init(VaadinRequest request) {
VerticalLayout mainLayout = new VerticalLayout();
HorizontalLayout buttonLayout = new HorizontalLayout();
springViewDisplay = new Panel();
buttonLayout.addComponent(new Button("1", event -> getNavigator().navigateTo(FirstView.VIEW_NAME)));
buttonLayout.addComponent(new Button("2", event -> getNavigator().navigateTo(SecondView.VIEW_NAME)));
mainLayout.addComponents(buttonLayout, springViewDisplay);
setContent(mainLayout);
}
#Override
public void showView(View view) {
springViewDisplay.setContent((Component) view);
}
/* VIEWS */
#UIScope
#SpringView(name = FirstView.VIEW_NAME)
public static class FirstView extends HorizontalLayout implements View {
public static final String VIEW_NAME = "";
#PostConstruct
private void init() {
System.out.println("Created first view");
addComponent(new Label("First view - " + LocalDateTime.now()));
}
#Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
// no-op
}
}
#SpringView(name = SecondView.VIEW_NAME)
#UIScope
public static class SecondView extends HorizontalLayout implements View {
public static final String VIEW_NAME = "secondView";
#PostConstruct
private void init() {
System.out.println("Created second view");
addComponent(new Label("Second view - " + LocalDateTime.now()));
}
#Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
// no-op
}
}
}
As you'll notice in the animation below, when navigating to the second view a new instance is always created, while navigating to the first one will reuse the initial instance:

Libgdx multiple screens

Thanks to the help I got with my other problems on this forum, I managed to advance my project, but yet another obstacle appears in my way.
I am having trouble implementing multiple Screens in libgdx for java. I would like to know how can I implement multiple screens (one for the main menu, one for play, one for loading screen, ...).
An example or some explanations of how should I structure my screen classes would be really helpful. I tried implementing my own screen manager but that didn't go very well... Also some pointers on how should I dispose screens, since creating screens every time you go from main menu to play or to options menu isn't a very good idea. Any ideas or code example or advice is much appreciated.
What I have now are some classes of game screens which when you render them they will draw some GUI on the screen, but functions like the back button don't work since I don't know how to make the link between them.
Let's say you got 3 screens, MainMenuScreen, OptionsScreen, GameScreen.
First you need to declare them in your main class.
It will look like this
public class MainClass extends Game implements ApplicationListener {
private GameScreen gameScreen;
private MenuScreen menuScreen;
private OptionsScreen optionsScreen;
#Override
public void create() {
}
setGameScreen()
{
gameScreen=new GameScreen(this);
setScreen(gameScreen);
}
setMenuScreen()
{
menuScreen=new menuScreen(this);
setScreen(menuScreen);
}
setOptionsScreen()
{
optionsScreen=new OptionsScreen(this);
setScreen(gameScreen);
}
#Override
public void dispose() {
super.dispose();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
super.render();
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
}
#Override
public void pause() {
super.pause();
}
#Override
public void resume() {
super.resume();
}
}
Now every screen you got, needs to have a MainClass variable and a constructor of it.
Lets say for the GameScreen class, it will be like
public class GameScreen implements Screen{
private MainClass mainClass;
public GameScreen(MainClass mc)
{
mainClass=mc;
}
// your methods (show,render, pause, etc)
}
Now when you want to change the screen just use in your screen
mainClass.setMenuScreen();

Does Subject.Subscribe only work in a static instance (or am I missing something)

I'm mucking about with reactive extensions and Iv'e hit a snag that I can't for the life of me work out what the cause is.
If I use a .NET 4 console mode app, where everything is static as follows:
using System;
using System.Reactive.Subjects;
using FakeDal;
using FakeDal.Entites;
using RxProducer;
namespace Runner
{
class Program
{
private static readonly Subject<DaftFrog> _subject = new Subject<DaftFrog>();
private static readonly Repository<DaftFrog> _frogRepo = new Repository<DaftFrog>();
static void Main()
{
_subject.Subscribe(RespondToNewData);
}
private static void RespondToNewData(DaftFrog frog)
{
_frogRepo.Save(frog);
}
}
}
DaftFrog is just a test class in my fake DAL class, this is a simple .NET 4 Class library project, the DaftFrog class, is a simple poco with a few fields in, the dal.save method just simply does a console.WriteLine of a field in the DaftFrog object.
Both classes are just simple stand in's for the real things once I get around to making the RX code work.
Anyway, back to the problem, so the code above works fine, and if I do a few
_subject.OnNext(new DaftFrog());
calls, the fake dal class, prints out what I expect and everything works fine...
HOWEVER>....
If I then transport this code as is, to a class library, and then new up that class library from within my "static program" as follows:
using System.Reactive.Subjects;
using FakeDal;
using FakeDal.Entites;
namespace RxProducer
{
public class Producer
{
private readonly Subject<DaftFrog> _subject = new Subject<DaftFrog>();
private readonly Repository<DaftFrog> _frogRepo = new Repository<DaftFrog>();
private int _clock;
public void Start()
{
_subject.Subscribe(RespondToNewData);
}
public void Stop()
{
}
public void Tick()
{
if(_clock % 5 == 0)
{
DaftFrog data = new DaftFrog();
_subject.OnNext(data);
}
_clock++;
}
private void RespondToNewData(DaftFrog frog)
{
_frogRepo.Save(frog);
}
}
}
And then use that class in my program
using System;
using RxProducer;
namespace Runner
{
class Program
{
private static readonly Producer _myProducer = new Producer();
static void Main()
{
_myProducer.Start();
while(!line.Contains("quit"))
{
_myProducer.Tick();
line = Console.ReadLine();
}
_myProducer.Stop();
}
}
}
Then my project fails to compile.
Specifically it fails on the line:
_subject.Subscribe(RespondToNewData);
in the RxProducer class library, mores the point, the error the compiler throws back makes little sense either:
Error 1 The best overloaded method match for 'System.Reactive.Subjects.Subject<FakeDal.Entites.DaftFrog>.Subscribe(System.IObserver<FakeDal.Entites.DaftFrog>)' has some invalid arguments H:\programming\rxtesting\RxProducer\Producer.cs 17 7 RxProducer
Error 2 Argument 1: cannot convert from 'method group' to 'System.IObserver<FakeDal.Entites.DaftFrog>' H:\programming\rxtesting\RxProducer\Producer.cs 17 26 RxProducer
At first I thought that it might have been the static thing, so I made everything in the class library static, and that made no difference at all.
Iv'e really not done much with Rx until now, but I work with C# and VS 99% of the time, so I'm aware that the error is telling me it can't convert a type of some description, I just don't understand why it's telling me that, esp when the code works perfectly in the static program, but not in a class library.
Shawty
UPDATE
Second thoughts, I just know there are going to be those who insist that I post the fakedal and daft frog definitions, even though IMHO they won't be required, but to pacify the hordes of pretenders who will ask here they are :-)
using System;
namespace FakeDal
{
public class Repository<T>
{
public void Save(T entity)
{
Console.WriteLine("Here we write T to the database....");
}
}
}
namespace FakeDal.Entites
{
public class DaftFrog
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsTotalyDaft { get; set; }
}
}
Include using System; into file where you have Producer, this will help to convert RespondToNewData to IObserver<T>.
Sounds like the compiler is having trouble inferring the Action...might be missing a using statement for the relevant extension method. Alternatively, try either of:
_subject.Subscribe ((Action<DaftFrog>) RespondToData);
Or:
var obs = Observer.Create ( I forget the overload );
_subject.Subscribe( obs);

Moq and Command Pattern .I am struggling can you help?

New to the world of TDD and I have soon find out that mocking at times is not as easy.
We are using MOQ at work so I need to learn how to do this using moq
I have some code using the command pattern and works a treat.However If were to test drive it I would not know how to do it implementing the code below.
I have done the following
Created BaseToolStripMenuItem:ToolStripMenuItem and added a Command Property (see below)
Created a windows form and added a menuStrip with 2 item Open and Exit
In the form I just add to map the command to a button and all works a treat.
I would like to change the code so that I can UnitTest using Moq but cannot see how???
Can you help?
Any suggestions?
Thanks a lot!!
public interface ICommand
{
void Execute()
}
public abstract class BaseCmd :ICommand
{
protected ProcessMenuCommand ProcessCommand;
protected MenuCommandFactory Factory;
protected BaseCmd(ProcessMenuCommand processMenuCommand, MenuCommandFactory cmdfactory)
{
ProcessCommand = processMenuCommand;
Factory = cmdfactory;
}
abstract public void Execute();
}
public class BaseToolStripMenuItem : ToolStripMenuItem
{
public BaseToolStripMenuItem()
{
Click += MenuItemClick;
Command = null;
}
public BaseCmd Command { get; set; }
private void MenuItemClick(object sender, EventArgs args)
{
if (Command != null) Command.Execute();
}
}
public class MenuCommandFactory
{
private readonly ProcessMenuCommand _processMenuCommand;
public MenuCommandFactory(ProcessMenuCommand processMenuCommand)
{
_processMenuCommand = processMenuCommand;
}
public OpenFileCmd OpenFile()
{
return new OpenFileCmd(_processMenuCommand,this);
}
public ExitCmd Exit()
{
return new ExitCmd(_processMenuCommand, this);
}
}
public class OpenFileCmd:BaseCmd
{
public OpenFileCmd(ProcessMenuCommand processMenu,MenuCommandFactory menuCommandFactory)
:base(processMenu,menuCommandFactory)
{
}
public override void Execute()
{
ProcessCommand.OpenFile();
}
}
public class ProcessMenuCommand
{
public void OpenFile()
{
MessageBox.Show("Open a file");
}
public void Exit()
{
MessageBox.Show("Exiting");
}
}
public class ExitCmd:BaseCmd
{
public ExitCmd(ProcessMenuCommand processMenu, MenuCommandFactory menuCommandFactory)
:base(processMenu,menuCommandFactory)
{
}
public override void Execute()
{
ProcessCommand.Exit();
}
}
//In the form
public partial class Form1 : Form
{
private ProcessMenuCommand menuCommandProcessor;
private MenuCommandFactory factory;
public Form1()
{
InitializeComponent();
// Created editor and factory.
menuCommandProcessor = new ProcessMenuCommand();
factory = new MenuCommandFactory(menuCommandProcessor);
// Get concrete command objects from factory and assign to corresponding menu items and tool strip buttons.
tsOpen.Command = factory.OpenFile();
tsExit.Command = factory.Exit();
}
}
However If were to test drive it I would not know how to do it implementing the code below
The idea about TDD is that it drives you towards an implementation. There are many implementations you could never arrive at using TDD, so your question doesn't really make much sense.
Try to write some tests that drive you towards your goal without having a preconceived image of the solution at which you wish to arrive. It will often turn out that you end up at an entirely different (and better) place than what you originally thought.
A simple Novice Rule: no abstract classes. Try designing again with only interfaces and concrete classes. You'll notice it's easier to test-drive the result.
As for "how to TDD a Command object", a Command is just a class that provides a single action. Test-drive it the same way you would test-drive any method, except you name the method Execute().

Resources