I am writing an Eclipse plugin(And RCP application) using SWT. In one of the views, I have 4 tabs and in couple of tabs I have many composites created with different textbox, checkbox and combobox(Tablecombo) controls. In one of the tab page, I get the org.eclipse.swt.SWTError: No more handles error. I read through multiple forum posts and see that this might be a resource leak but I am not sure how to find it in the RCP application. Also if I write a small test to create 10000 composites, I get the same SWT No more handles error.
Here is the code
public static void main( String[] args )
{
Display display = new Display();
Shell shell = new Shell( display );
shell.setBounds( 10, 10, 350, 200 );
shell.setLayout( new FillLayout() );
for ( int i = 0; i < 10000; i++ )
{
Composite comp = new Composite( shell, SWT.NONE );
}
shell.open();
while ( !shell.isDisposed() )
{
if ( !display.readAndDispatch() )
display.sleep();
}
display.dispose();
}
Related
I use the controlP5 library and did not find how to change the layout of the tabs.
Tried various tricks but .setPosition is not responsive.
import controlP5.*;
ControlP5 cp5;
int myColorBackground = color(128);
int sliderValue = 100;
void setup() {
size(700,400);
noStroke();
cp5 = new ControlP5(this);
// By default all controllers are stored inside Tab 'default'
// add a second tab with name 'extra'
cp5.addTab("extra")
.setColorBackground(color(0, 160, 100))
.setColorLabel(color(255))
.setColorActive(color(255,128,0))
;
// if you want to receive a controlEvent when
// a tab is clicked, use activeEvent(true)
cp5.getTab("default")
.activateEvent(true)
.setLabel("my default tab")
.setPosition (120 , 230)
.setId(1)
;
cp5.getTab("extra")
.activateEvent(true)
.setPosition (150, 260)
.setId(2)
;
It seems that Swing auto decorate some Arabic words by making them look some kind calligraphic. One of those words is Muhammad which is spelled in Arabic as محمد.
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class TestProject extends JFrame {
public static void main(String[] args) {
TestProject frame = new TestProject();
frame.setVisible(true);
}
public TestProject() {
this.setSize(200, 100);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("محمد");
label.setFont(new Font("Arial", Font.BOLD, 28));
this.add(label);
}
}
The problem is applied to all widely used Fonts at least.
I'm using Windows 10 & Java 8. I've tried the same program on another PC (also Windows 10) same problem.
How can we disable that?
This seems to be a bug in the old (i.e. up to Java 8) font rendering engine.
This is how it looks with Java 8 on my machine:
And this is the result with Java 9:
I don’t know whether an explicit bug report has been reported for this specific issue. But the font engine has been replaced entirely, due to JEP 258: HarfBuzz Font-Layout Engine.
Replace the existing ICU OpenType font-layout engine with HarfBuzz.
So it’s not surprising that bugs of the old font rendering are gone.
(Caveat: I am not literate in Arabic.)
Appears to be font related
By default, I do not get your longer representation (3 words?) as seen in your screenshot.
When I write a minimal Swing app with the text "محمد" I get that short string (4 characters?) that you want.
When using specific fonts, I do get what looks to my untrained eye to be the calligraphic rendering you seek to avoid.
Note that my string was not your string. I copied from Google Translate, translating Muhammad as indicated in your Question.
https://translate.google.com/?sl=en&tl=ar&text=Muhammad%0A&op=translate
I wrote this minimal Swing app with just a JLabel, enhanced only by increasing font size.
package work.basil.example;
import javax.swing.*;
import java.awt.*;
/**
* Hello world!
*/
public class App {
public static void main ( String[] args ) {
System.out.println( Runtime.version() );
javax.swing.SwingUtilities.invokeLater( () -> createAndShowGUI() );
}
private static void createAndShowGUI () {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated( true );
//Create and set up the window.
JFrame frame = new JFrame( "Test Arabic rendering" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
//Add the ubiquitous "Hello World" label.
JLabel label = new JLabel( "محمد" );
label.setFont( new Font( label.getFont().getName() , label.getFont().getStyle() , 40 ) ); // Override default font size.
System.out.println( "Font name: " + label.getFont().getName() + " | " + "Font style: " + label.getFont().getStyle() );
frame.getContentPane().add( label );
//Display the window.
frame.pack();
frame.setVisible( true );
}
}
When run on my MacBook Pro (13-inch, M1, 2020), Apple Silicon (not Intel), 16 gigs of memory. The OS is macOS Big Sur, 11.5.1. Using early-access version of Java 17 (17+35-2724) from this page.
(By the way, this is the kind of MCVE you should have posted with your Question.)
The result of my font query is:
Font name: Lucida Grande | Font style: 0
… but I suspect that is the default font of the JLabel widget rather than the actual font used in rendering those Arabic characters. As I vaguely recall, recent versions of macOS are rich with a variety of fonts specifically for Arabic. See: Fonts included with macOS Big Sur for three lists: fonts included, fonts available for download, and older fonts available for document support. Using the Font Book app bundled with macOS, and defining a "smart collection" where languages include Arabic, I get a list of 32 such fonts installed by default in macOS Big Sur. (The four items for Pragmata Pro do not apply — that is a commercial font which I purchased, and which I highly recommend for developers.)
I ran this modified version of the code from Answer by Andrew Thompson on the same macOS Big Sur described above.
package work.basil.text;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
public class TestProject extends JFrame {
public static void main ( String[] args ) {
TestProject frame = new TestProject();
frame.setVisible( true );
}
public TestProject () {
this.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
this.setLayout( new FlowLayout() );
String input = "محمد";
String[] fontFamilies = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
for ( String fontFamily : fontFamilies ) {
Font font = new Font( fontFamily , Font.PLAIN , 40 );
if ( font.canDisplayUpTo( input ) < 0 ) {
JLabel label = new JLabel( input );
label.setFont( font );
label.setBorder( new TitledBorder( fontFamily ) );
this.add( label );
}
}
this.pack();
}
}
Here is a screenshot of the result.
Try running the code below. It produced this image on my range of installed fonts.
Note also that Arial (a sans-serif or undecorated font) seems to default to Times New Roman (a serif or decorated font) for its Arabic glyphs. This is a common thing for fonts (or systems, not sure) to do, and it produces rather odd renderings when sans-serif fonts are replaced with serif fonts.
Also note this system has 255 fonts installed, but only 23 of those support Arabic characters.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class TestProject extends JFrame {
public static void main(String[] args) {
TestProject frame = new TestProject();
frame.setVisible(true);
}
public TestProject() {
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel p = new JPanel(new GridLayout(0, 5));
String arabic = "محمد";
String[] fontFamilies = GraphicsEnvironment.
getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
for (String fontFamily : fontFamilies) {
Font font = new Font(fontFamily, Font.PLAIN, 25);
if (font.canDisplayUpTo(arabic) < 0) {
JLabel label = new JLabel(arabic);
label.setFont(font);
label.setBorder(new TitledBorder(fontFamily));
p.add(label);
}
}
this.add(new JScrollPane(p));
this.pack();
}
}
I have problem with xfwm4. Using following code:
Shell s = windowVector.get(0).getShell();
s.setActive();
Shell window that is covered by other shells is not raised above. Using kwin (KDE window manager) it works correctly. Shell is created using following constructor:
shell = new Shell(mainShell, SWT.NO_TRIM | SWT.MODELESS);
In both cases SWT method:
OS.gdk_window_focus (window, OS.GDK_CURRENT_TIME);
is called but in xfwm4 shell get focus and is NOT raised above all other shell windows (in my application). Is this bug in xfwm4? Maybe some configuration issue or I am missig something.
EDIT:
I might be not precise. Shell that i try to setActive is "under" other child shells. Following code explains and simplfy what I am trying to achieve:
Shell mainShell = new Shell(Display.getDefault(), SWT.NO_TRIM);
mainShell.setBounds(0, 0, 300, 200);
mainShell.open();
final Shell shell1 = new Shell(mainShell, SWT.NO_TRIM | SWT.MODELESS);
shell1.setBounds(0, 0, 300, 200);
shell1.open();
Shell shell2 = new Shell(mainShell, SWT.NO_TRIM | SWT.MODELESS);
shell2.setBounds(0, 0, 300, 200);
shell2.open();
Thread thread = new Thread() {
#Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("Raise shell1 above");
shell1.setActive();
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
while( !mainShell.isDisposed()) {
if( !Display.getDefault().readAndDispatch()) {
Display.getDefault().sleep();
}
}
Display.getDefault().dispose();
This code works correctly in kwin, in xfwm4 shell1 stays "under" shell2 and remains hidden.
I can't speak about xfwm4 specifically but yes, many window managers have some form of input stealing prevention.
You don't want any random application being allowed to steal your focus or force your attention away from what you are doing.
How they implement this behaviour differs between window managers however. Most should (ideally) allow the currently focused application to give focus to a newly created window of that application but I imagine not all do that.
Using the SWT ScrollableComposite, is there an easy way in which to set the scrollbar position to jump in such a way that a particular element will be positioned at the top?
For example, if I had such a composite filled with 26 labels going down with the letters of the alphabet in order:
...then, say that I want to set my view to the "J" label and have the scrollbar position set like this:
(This is only example - if I really wanted to do what I am describing here, I would clearly just use a listbox or a table for my letters instead.)
This is similar to how Internet Browsers work when jumping to a specific tag within a page.
This can likely be done with a bunch of manual measurement calculations, if necessary, but my hope is that something simpler exists.
I believe you are looking for below method on ScrolledComposite
org.eclipse.swt.custom.ScrolledComposite.showControl(Control) //make it visible in view port
org.eclipse.swt.custom.ScrolledComposite.setOrigin(Point) //sets left corner coordinates, read SWT docs
Updated Answer:
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
Map<String,Control> controlMap = new HashMap<String,Control>();
final ScrolledComposite scrollComposite = new ScrolledComposite(shell,
SWT.V_SCROLL | SWT.BORDER);
final Composite parent = new Composite(scrollComposite, SWT.NONE);
for (int i = 0; i <= 50; i++) {
Label label = new Label(parent, SWT.NONE);
String index = String.valueOf(i);
controlMap.put(index, label);
label.setText(index);
}
GridLayoutFactory.fillDefaults().numColumns(1).applyTo(parent);
scrollComposite.setContent(parent);
scrollComposite.setExpandVertical(true);
scrollComposite.setExpandHorizontal(true);
scrollComposite.addControlListener(new ControlAdapter() {
public void controlResized(ControlEvent e) {
Rectangle r = scrollComposite.getClientArea();
scrollComposite.setMinSize(parent.computeSize(r.width,
SWT.DEFAULT));
}
});
shell.open();
Control showCntrl = controlMap.get(String.valueOf(5));
if(showCntrl != null){
scrollComposite.setOrigin(showCntrl.getLocation());
}
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
I've a Window which contains two ContentPanel (horizontally), one with a Image into it and the other one with some text. The problem is that my text is truncated : it's going out of the Window...
Window win = new Window();
win.setLayout( new FillLayout() );
win.setMinWidth( 250 );
win.setHeight( 120 );
ContentPanel content = new ContentPanel( new RowLayout( Orientation.HORIZONTAL ) );
ContentPanel iconePanel = new ContentPanel( new FillLayout() );
iconePanel.add(myImage);
content.add( iconePanel, new RowData( 48, 1 ) );
Text textPanel = new Text();
textPanel.setText( msg );
content.add( textPanel, new RowData( -1, 1 ) );
win.add( content );
win.show();
How can I keep the text in the panel?
Its necessary that you should have a good understanding of different panels in the GXT,There is another trick by adjusting the padding size,Its better you use a firebug and adjust the Layout using Firebug,it will help a lot for adjusting the window.