Mudar resolução do X no java --Linux--[Resolvido]

ola…eu estava testando o seguinte tutorial da sun:

http://java.sun.com/docs/books/tutorial/extra/fullscreen/example-1dot4/DisplayModeTest.java

o problema é que ele só executa direito uma vez…na segunda ele reclama:

Exception in thread "AWT-EventQueue-0" java.lang.UnsupportedOperationException: Cannot change display mode

ai eu tenho que reiniciar o Xorg pra que ele funcione novamente…alguem sabe pq isso ocorre na segunda vez?

outra coisa…eu tentei imitar o exemplo…eu seto a resolução pra 640x480 e quando volto ela pro normal, recebo:

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

e fiz assim:

 DisplayMode originalDM = device.getDisplayMode();
DisplayMode[] modes = device.getDisplayModes();
device.setDisplayMode(modes[11]);
// depois pra voltar ao normal por um button
device.setDisplayMode(originalDM);

foi um Ctrl+c Ctrl+v no codigo…

Qual distribuição Linux você está utilizando? Alguns efeitos visuais do Ubuntu, por exemplo, geram problemas com mudança de resolução e aplicação 3D (usar Java 3D no Ubuntu com os efeitos visuais ativados é suicídio! Trava tudo e depois ele faz logoff sozinho!).

Quanto ao java.lang.UnsupportedOperationException, existe um método isDisplayChangeSupported() da classe GraphicsDevice. Ou seja, faça uma verificação se é possível mudar para fullscreen antes de realizar a operação. Algo como:

if (device.isDisplayChangeSupported()) {
 DisplayMode originalDM = device.getDisplayMode();
DisplayMode[] modes = device.getDisplayModes();
device.setDisplayMode(modes[11]);
// depois pra voltar ao normal por um button
device.setDisplayMode(originalDM);
} else {
System.err.prinln("Fullscreen não suportado!");
}

Mais uma observação: seu código é executado como acima? Se for, o java.lang.OutOfMemoryError é explicado: você muda a resolução de tela duas vezes num intervalo de alguns milissegundos. Para funcionar bem deveria haver um tempo razoavel entre as trocas.

opa…
bom… primeiro vamos ao meu codigo…

eu adicionei essa linha que vc falou e …ele nem entra dentro do if…retorna false esse metodo…

só pra testar coloquei assim:

		 if (device.isDisplayChangeSupported()) {  
			    DisplayMode originalDM = device.getDisplayMode();
					// testes de fullscreen em 640,480
			    DisplayMode[] modes = device.getDisplayModes();
			    for(int x=0 ; x <modes.length;x++){
			    System.out.println(modes[x].getWidth());
			    System.out.println(x);
			    device.setFullScreenWindow(f);
				device.setDisplayMode(modes[11]);
				System.out.println("TESTE");
				max.addActionListener(new MyActionListener(device,originalDM));
			    }}

e ele nem exibiu o “TESTE”…outra coisa…a parte

// depois pra voltar ao normal por um button  
device.setDisplayMode(originalDM);  

fica dentro de um listener…que só executa quando eu clico no botao …e o demo da sun eu clico pra mudar de resolução na mesma velocidade que faço no meu teste… e mesmo assim só no meu teste da outOfMemory

vc teria ai um codigo limpo…só com a parte que muda de resolução?
geralmente eu consigo abstrair só a parte que eu vou usar dos demos da sun…mas nessa me pareceu muito bagunçado…ta cheio de Table, JPanes e metodos pra transformar o retorno deles em DisplayChanges que eu acabei me confundindo…

o mais legal de tudo é que o demo usa o isDisplayChangeSupported que retorna true…e o meu false…

eu ja ia esquecendo…eu uso Slackware 12.1 + KDE/fluxbox, e eu desativo o compiz quando vou usar o eclipse, alias quase nunca uso o compiz…só quando vem gente em casa hehehe…

[quote=ThankChenus]opa…
bom… primeiro vamos ao meu codigo…

eu adicionei essa linha que vc falou e …ele nem entra dentro do if…retorna false esse metodo…

só pra testar coloquei assim:

		 if (device.isDisplayChangeSupported()) {  
			    DisplayMode originalDM = device.getDisplayMode();
					// testes de fullscreen em 640,480
			    DisplayMode[] modes = device.getDisplayModes();
			    for(int x=0 ; x <modes.length;x++){
			    System.out.println(modes[x].getWidth());
			    System.out.println(x);
			    device.setFullScreenWindow(f);
				device.setDisplayMode(modes[11]);
				System.out.println("TESTE");
				max.addActionListener(new MyActionListener(device,originalDM));
			    }}

e ele nem exibiu o “TESTE”…outra coisa…a parte

// depois pra voltar ao normal por um button  
device.setDisplayMode(originalDM);  

fica dentro de um listener…que só executa quando eu clico no botao …e o demo da sun eu clico pra mudar de resolução na mesma velocidade que faço no meu teste… e mesmo assim só no meu teste da outOfMemory

vc teria ai um codigo limpo…só com a parte que muda de resolução?
geralmente eu consigo abstrair só a parte que eu vou usar dos demos da sun…mas nessa me pareceu muito bagunçado…ta cheio de Table, JPanes e metodos pra transformar o retorno deles em DisplayChanges que eu acabei me confundindo…

o mais legal de tudo é que o demo usa o isDisplayChangeSupported que retorna true…e o meu false…

eu ja ia esquecendo…eu uso Slackware 12.1 + KDE/fluxbox, e eu desativo o compiz quando vou usar o eclipse, alias quase nunca uso o compiz…só quando vem gente em casa hehehe…[/quote]

:lol: Só quando vem gente em casa é muito boa…

Quanto ao seu problema, se o método retorna false, ou temos algum problema de configuração ou seu computador está meio “fraquinho” mesmo. Só será possível mudar a resolução se o método retornar true. Mas o mais estranho de tudo é que o exemplo da Sun funciona no seu PC…

Teste esse código aqui e poste os resultados:

package swing;

import java.awt.DisplayMode;
import java.awt.FlowLayout;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.TreeMap;

import javax.swing.JComboBox;
import javax.swing.JFrame;

public class FullScreen extends JFrame {

	private static final long serialVersionUID = 1L;
	private JComboBox comboBox;
	private GraphicsDevice device;
	private TreeMap<String, DisplayMode> displayModesMap;

	public FullScreen() {
		super();
		initGUI();
	}

	public static void main(String[] args) {
		new FullScreen();
	}

	private JComboBox getComboBox() {
		if (comboBox == null) {
			comboBox = new JComboBox(getDisplayModesMap().keySet().toArray());
			comboBox.setSelectedIndex(-1);
			comboBox.addItemListener(new ItemListener() {

				@Override
				public void itemStateChanged(ItemEvent e) {
					mudaResolucao();
				}
			});
		}
		return comboBox;
	}

	private GraphicsDevice getDevice() {
		if (device == null) {
			device = GraphicsEnvironment.getLocalGraphicsEnvironment()
					.getDefaultScreenDevice();
		}
		return device;
	}

	private TreeMap<String, DisplayMode> getDisplayModesMap() {
		if (displayModesMap == null) {
			displayModesMap = new TreeMap<String, DisplayMode>();
			String name = null;
			for (DisplayMode dm : getDevice().getDisplayModes()) {
				name = String.format("%d, %d, %d, %d", dm.getWidth(), dm
						.getHeight(), dm.getBitDepth(), dm.getRefreshRate());
				displayModesMap.put(name, dm);
			}
		}
		return displayModesMap;
	}

	private void initGUI() {
		setLayout(new FlowLayout(FlowLayout.CENTER, 5, 30));
		add(getComboBox());
		setUndecorated(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		if (getDevice().isFullScreenSupported()) {
			getDevice().setFullScreenWindow(this);
		} else {
			System.err.println("Modo tela cheia não suportado!");
			dispose();
		}
	}

	private void mudaResolucao() {
		if (getDevice().isDisplayChangeSupported()) {
			getDevice().setDisplayMode(
					getDisplayModesMap().get(getComboBox().getSelectedItem()));
		} else {
			System.err.println("Não é possível mudar a resolução!");
			dispose();
		}
	}

}

Modo tela cheia não suportado! :shock:

caramba…o da sun continua funcionando na primeira vez… :?

Dê uma olhada no método begin() no código no site da Sun e sugiro que faça algumas adaptações no código, seguindo aquele padrão. Isso garante que o programa seja funcional, mesmo que o fullscreen não seja suportado. Ficaria algo como (principal mudança está no método initGUI):

package swing;

import java.awt.DisplayMode;
import java.awt.FlowLayout;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.TreeMap;

import javax.swing.JComboBox;
import javax.swing.JFrame;

public class FullScreen extends JFrame {

	private static final long serialVersionUID = 1L;
	private JComboBox comboBox;
	private GraphicsDevice device;
	private TreeMap<String, DisplayMode> displayModesMap;

	public FullScreen() {
		super();
		this.initGUI();
	}

	public static void main(final String[] args) {
		new FullScreen();
	}

	private JComboBox getComboBox() {
		if (this.comboBox == null) {
			this.comboBox = new JComboBox(this.getDisplayModesMap().keySet()
					.toArray());
			this.comboBox.setSelectedIndex(-1);
			this.comboBox.addItemListener(new ItemListener() {

				@Override
				public void itemStateChanged(final ItemEvent e) {
					FullScreen.this.mudaResolucao();
				}
			});
		}
		return this.comboBox;
	}

	private GraphicsDevice getDevice() {
		if (this.device == null) {
			this.device = GraphicsEnvironment.getLocalGraphicsEnvironment()
					.getDefaultScreenDevice();
		}
		return this.device;
	}

	private TreeMap<String, DisplayMode> getDisplayModesMap() {
		if (this.displayModesMap == null) {
			this.displayModesMap = new TreeMap<String, DisplayMode>();
			String name = null;
			for (final DisplayMode dm : this.getDevice().getDisplayModes()) {
				name = String.format("%d, %d, %d, %d", dm.getWidth(), dm
						.getHeight(), dm.getBitDepth(), dm.getRefreshRate());
				this.displayModesMap.put(name, dm);
			}
		}
		return this.displayModesMap;
	}

	private void initGUI() {
		this.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 30));
		this.add(this.getComboBox());
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		boolean suportaTelaCheia = this.getDevice().isFullScreenSupported();
		setResizable(!suportaTelaCheia);
		setUndecorated(suportaTelaCheia);
		if (suportaTelaCheia) {
			this.getDevice().setFullScreenWindow(this);
		} else {
			System.err.println("Modo tela cheia não suportado!"
					+ "Rodando no modo janela.");
			this.pack();
			setVisible(true);
		}
		getComboBox().setEnabled(getDevice().isDisplayChangeSupported());
		if (!getDevice().isDisplayChangeSupported()) {
			System.err.println("A troca de resolução não é possível!");
		}
	}

	private void mudaResolucao() {
		this.getDevice().setDisplayMode(
				this.getDisplayModesMap().get(
						this.getComboBox().getSelectedItem()));
	}

}

É importante levar em consideração que fullscreen é uma coisa e displayModeChange é outra, que não dependem diretamente entre si (apesar de que geralmente muda-se a resolução apenas no modo tela cheia).

ok…segundo problema resolvido…faltando agora o principal… assim como o da sun…o seu funcionou perfeitamente na primeira vez…mas na segunda:

Modo tela cheia não suportado!Rodando no modo janela.
A troca de resolução não é possível!
editado------------
e umas perguntas:
o fato de você ter usado “final DisplayMode” tem algo de especial? t
odas as vezes que eu uso o “for if”(acho que o nome é esse)
nao coloco esse final… essa teg server pra declarar “variaveis nao variantes”(esqueci o nome…acabei de acordar) que uma vez declarado seu conteudo, ela nao pode mais ser alterada certo?
que efeito isso teria no codigo?
legal…ja tinha ouvido falar de TreeMap mas nunca usado…é mais rapida pra consultas/alterações do que o ArrayList ?

editado---------------------

bom gente :oops: …eu estava usando o JDK6u6 no slackware 12.1…
ai, hoje eu instalei o slackware 12.2 que vem com o JDK6u11…
e parou de dar esse problema…esta funcionando quantas vezes eu executar…
:lol: só nao sei se o que resolveu foi atualizar a versao do jdk ou a versao do slackware(ou ambos)
mas em fim…
to só aguardando a resposta para a parte do “final” que eu perguntei acima e ja marco esse topico como resolvido!

O modificador final, serve para indicar que a variável que foi declarada (ou recebido como parâmetro) não terá sua referência alterada (ou seja, não executaremos comandos de atribuição com essa variável). No caso, não faz diferença, mas seria apenas uma forma de não fazer atribuições desnecessárias (ou mesmo sem querer) e de avisar a JVM que não haverá mais atribuições.

Quanto ao TreeMap, nota-se ao menos um grande diferença em relação ao ArrayList:

Map<String, DisplayMode> mapa = new TreeMap<String, DisplayMode>();
// dois parâmetros no Generics!
List<String> lista = new ArrayList<String>();
// apenas um tipo no Generics!

As classes EnumMap, HashMap, TreeMap, Properties e todas as outra que implementam Map, funcionam com uma espécie de “tabela” onde cada elemento da primeira coluna corresponde a um da segunda. Por exemplo, na classe FullScreen, uma possível representação do mapa:

String / DisplayMode
800, 600, 32, 60 / DisplayMode@23435f
800, 600, 16, 60 / DisplayMode@7d5ef4
640, 320, 32, 60 / DisplayMode@942051
640, 320, 16, 60 / DisplayMode@f5e22a

Ou seja, são pares de elementos. Com isso, podemos ter em um só local as descrições para cada DisplayMode e um objeto do tipo DisplayMode proprimente dito.

Por que usar o TreeMap? Por que é um mapa navegável que mantém a ordem de seus elementos (diferente de HashMap, por exemplo).

Links a respeito:
Tutorial sobre Collections
Implementações da classe Map
Documentação da interface Map
Documentação da classe TreeMap