Múltiplas Janelas(JDialogs)

Olá pessoal, por muito venho pesquisando sobre um pequeno comportamento anômalo do sistema o qual estou implementando.

Eu estou fazendo um monitor de um servidor de impressão que utiliza Cups. Por isso, para cada impressora instalada no servidor, uma thread eh criada em meu sistema:

public static void startCupsMonitor() throws Exception {
	for (CupsPrinter cupsPrinter : PrintJobsUtils.getAllPrinters()) {
		SwingUtilities.invokeLater( () -> new PrinterWorker( cupsPrinter.getName() ).execute() );
	}
}

Como se pode perceber, estou utilizando um SwingWorker para fazer o “processamento” do monitor. Dentro do método doInBackground(), eu chamo o método publish( printJobAttributes ) e, consequentemente, no método process eu realizado o seguinte:

@Override
protected void process(List<PrintJobAttributes> data) {
	
	for (PrintJobAttributes jobAttributes : data) {
		
		if (printQueue.getDefaultTableModel().getRowCount() == 0) {
			printQueue.getDefaultTableModel().addRow( new Object[]{jobAttributes.getJobID(), jobAttributes.getJobName(),
				jobAttributes.getSize()} );
		} else {
			int duplicateRow = -1;
			for (int row = 0; row < printQueue.getDefaultTableModel().getRowCount(); row++) {
				if (jobAttributes.getJobID() == (int) printQueue.getjTable().getValueAt( row, 0 )) {
					duplicateRow = row;
					break;
				}
			}
			if (duplicateRow == -1) {
				printQueue.getDefaultTableModel().addRow( new Object[]{jobAttributes.getJobID(), jobAttributes.getJobName(),
					jobAttributes.getSize()} );
			}
		}
	}
	printQueue.setVisible( true );
	printQueue.toFront();
}

O problema é que com essa abordagem múltiplas JDialogs, implementada logo abaixo, estão sendo abertas. Eu já tentei singleton, já tentei observer (mas acho que nesse caso não implementei de forma adequada), forcei a classe do Jdialog para Final. Simplesmente não sei mais o q fazer… Por isso me resta perguntar, por estar utilizando o SW eu estou preso na condição que para cada SW será aberta uma janela?

Segue a view:

public class PrintQueue extends JDialog {

private JTable jTable;
private DefaultTableModel defaultTableModel = new DefaultTableModel();

/**
 * -
 */
public PrintQueue() {
	this.setIconImage( ApplicationUtils.ICON_BUFFERED_IMAGE );
	this.setBounds( 100, 100, 450, 300 );
	this.setModalityType( ModalityType.APPLICATION_MODAL );
	this.setResizable( false );
	
	JPanel panelButtons = new JPanel();
	this.getContentPane().add( panelButtons, BorderLayout.SOUTH );
	
	JButton cancelPrintBtn = new JButton( "Cancelar Impress\u00E3o" );
	cancelPrintBtn.addActionListener( cancelActionEvent -> {
		System.out.println( "cancelActionEvent" );
	} );
	panelButtons.add( cancelPrintBtn );
	
	JButton releasePrintBtn = new JButton( "Liberar Impress\u00E3o" );
	releasePrintBtn.addActionListener( releaseActionEvent -> {
		System.out.println( "releaseActionEvent" );
	} );
	panelButtons.add( releasePrintBtn );
	
	JPanel tablePanel = new JPanel();
	this.getContentPane().add( tablePanel, BorderLayout.CENTER );
	tablePanel.setLayout( null );
	
	JScrollPane jScrollPane = new JScrollPane();
	jScrollPane.setBounds( 10, 11, 414, 207 );
	tablePanel.add( jScrollPane );
	
	this.initJTable( jScrollPane );
	
}


/**
 * -
 *
 * @param jScrollPane -
 */
private void initJTable(JScrollPane jScrollPane) {
	
	jTable = new JTable( defaultTableModel );
	
	TableCellRenderer tableCellRenderer = jTable.getTableHeader().getDefaultRenderer();
	JLabel headerTable = (JLabel) tableCellRenderer;
	headerTable.setHorizontalAlignment( JLabel.CENTER );
	
	defaultTableModel.addColumn( "N\u00BA Impress\u00E3o" );
	defaultTableModel.addColumn( "Nome da Impress\u00E3o" );
	defaultTableModel.addColumn( "Tamanho" );
	
	jTable.getColumnModel().getColumn( 0 ).setPreferredWidth( 100 );
	jTable.getColumnModel().getColumn( 1 ).setPreferredWidth( 339 );
	jTable.getColumnModel().getColumn( 2 ).setPreferredWidth( 100 );
	
	jScrollPane.setViewportView( jTable );
}


public DefaultTableModel getDefaultTableModel() {
	return defaultTableModel;
}

public JTable getjTable() {
	return jTable;
}

Posta o fonte da PrinterWorker.

public class PrinterWorker extends SwingWorker<Void, PrintJobAttributes> {

private String pName;
private List<PrintJobAttributes> printQueueArrayList = new ArrayList<>();
private PrintQueue printQueue = new PrintQueue();

public PrinterWorker(String pName) {
	this.pName = pName;
	printQueue.setTitle( "Fila de Impressão" );
}


@Override
protected Void doInBackground() throws Exception {
	CupsPrinter cupsPrinter;
	
	while (true) {
		List<PrintJobAttributes> printJobAttributesList;
		printJobAttributesList = PrintJobsUtils.getAllJobDetails( cupsPrinter );
		if (!printJobAttributesList.isEmpty()) {
			
			for (PrintJobAttributes printJobAttributes : printJobAttributesList) {
				if (printJobAttributes.getJobState() == JobStateEnum.PENDING_HELD) {
					if (!ApplicationUtils.cotainsId( printJobAttributes, printQueueArrayList )) {
						publish( printJobAttributes );
					}
				}
			}
			Thread.sleep( 1000 );
		}
	}
}

@Override
protected void process(List<PrintJobAttributes> data) {
	
	for (PrintJobAttributes jobAttributes : data) {
		
		if (printQueue.getDefaultTableModel().getRowCount() == 0) {
			printQueue.getDefaultTableModel().addRow( new Object[]{jobAttributes.getJobID(), jobAttributes.getJobName(),
				jobAttributes.getSize()} );
		} else {
			int duplicateRow = -1;
			for (int row = 0; row < printQueue.getDefaultTableModel().getRowCount(); row++) {
				if (jobAttributes.getJobID() == (int) printQueue.getjTable().getValueAt( row, 0 )) {
					duplicateRow = row;
					break;
				}
			}
			if (duplicateRow == -1) {
				printQueue.getDefaultTableModel().addRow( new Object[]{jobAttributes.getJobID(), jobAttributes.getJobName(),
					jobAttributes.getSize()} );
			}
		}
	}
	printQueue.setVisible( true );
	printQueue.toFront();
}

}`

É que cada PrintWorker cria seu próprio PrintQueue;

Não seria melhor cada PrintWorker acessar a mesma PrintQueue?

Ficaria algo mais ou menos assim:

public static void startCupsMonitor() throws Exception {
	PrintQueue unicaPrintQueue = new PrintQueue();
	for (CupsPrinter cupsPrinter : PrintJobsUtils.getAllPrinters()) {
		SwingUtilities.invokeLater( () -> new PrinterWorker( cupsPrinter.getName(), unicaPrintQueue ).execute() );
	}
}

Nossa funcionou como um gatinho…
Eu fui para a abordagem mais difícil (like Observer e Singleton) e esqueci de olhar essa besteira kkkk

Muito obrigado @staroski =]

1 curtida

Falando em abordagem difícil, se eu fosse você implementaria meu próprio TableModel para renderizar uma lista de PrintJobAttributes, fica bem mais simples do que ficar adicionando itens em um DefaultTableModel.

@staroski é que trabalhei sempre em Web Vou dar uma pesquisada aqui para ver como se faz =)