The default context menu of SWT Text in windows has several options that we did not want. As the default context menu is provided by the operating system and cannot be modified, I created a custom context menu with only basic Text operations such as delete, cut, copy and paste for the Text boxes.
The problem now is that when I copy text from another application and try pasting into the TextBox, the paste doesn't seem to work. But it works when we copy/cut text within the application itself.
Here is the code for copy and paste.
Paste Action:
private class PasteActionHandler extends Action {
/** Creates a new instance. */
private PasteActionHandler() {
...
setEnabled(false);
}
#Override
public void runWithEvent(Event event) {
if (activeTextControl != null && !activeTextControl.isDisposed()) {
activeTextControl.paste();
updateActionsEnableState();
return;
}
}
/**
* Updates the state of the Paste Action.
*/
public void updateEnabledState() {
if (activeTextControl != null && !activeTextControl.isDisposed()) {
boolean canPaste = false;
if (activeTextControl.getEditable()) {
Clipboard clipboard = new Clipboard(activeTextControl.getDisplay());
TransferData[] td = clipboard.getAvailableTypes();
for (int i = 0; i < td.length; ++i) {
if (TextTransfer.getInstance().isSupportedType(td[i])) {
canPaste = true;
break;
}
}
clipboard.dispose();
}
setEnabled(canPaste);
return;
}
setEnabled(false);
}
}
Copy Action:
private class CopyActionHandler extends Action {
private CopyActionHandler() {
...
setEnabled(false);
}
#Override
public void runWithEvent(Event event) {
if (activeTextControl != null && !activeTextControl.isDisposed()) {
activeTextControl.copy();
updateActionsEnableState();
return;
}
}
/**
* Updates the state of the {#link Action}.
*/
public void updateEnabledState() {
if (activeTextControl != null && !activeTextControl.isDisposed()) {
setEnabled(activeTextControl.getSelectionCount() > 0);
return;
}
setEnabled(false);
}
}
As you could see, I call the Text control's copy and paste functions to do the operations.
Also is there a way in SWT to get the system clipboard?
To copy something in the clipboard from SWT i use the code:
String textData = textControl.getText();
if (textData.length() > 0) {
org.eclipse.swt.dnd.Clipboard cb = new org.eclipse.swt.dnd.Clipboard(display);
org.eclipse.swt.dnd.TextTransfer textTransfer = org.eclipse.swt.dnd.TextTransfer.getInstance();
cb.setContents(new Object[]{textData}, new Transfer[]{textTransfer});
}
you can try that instead of activeTextControl.copy() function and see if it works
Related
( 1 ) Is there a way to listen for any clipboard updates (including Ctrl+C/X, PrtSc (screenshot) and changes made by other programs) in Java? I have tried this:
Toolkit.getDefaultToolkit().getSystemClipboard().addFlavorListener(new FlavorListener() {
#Override
public void flavorsChanged(FlavorEvent e) {
System.out.println("Copy detected");
}
});
This handles Ctrl+C changes well but doesn't notice changes which are not made by user manually, e.g. by screenshotting software or PrtSc button.
( 2 ) Is there a way to listen for paste actions (Ctrl+V, "paste" button, etc.)? I want something like that (or just with similar functionality):
// ...
#Override
public void prePaste(PasteEvent e) {
System.out.println("Paste detected");
e.cancel(); // reject the paste (so that user's Ctrl+V pastes nothing)
}
// ...
one way to capture when things are pasted into composites is to add a Listener "addKeyListener".
Java 8
KeyAdapter keyAdapter = new KeyAdapter()
{
#Override
public void keyPressed(KeyEvent keyEvent)
{
if(((keyEvent.getModifiers() & InputEvent.CTRL_MASK) != 0) && (keyEvent.getKeyCode() == KeyEvent.VK_V))
{
String text = null;
try
{
text = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor);
System.out.println(text);
}
catch(Exception e)
{
e.printStackTrace();
}
keyEvent.consume();
}
}
};
stringTF.addKeyListener(keyAdapter);
for java over version 9 you can use the following condition
if(((keyEvent.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) && (keyEvent.getKeyCode() == KeyEvent.VK_V))
{
// Code ....
}
In my ZK project with Java, I need to show a message box in which there needs to be a hyperlink, from which user can open another web page.
How can I achieve this?
According to the documentation, the customization of the MessageBox is rather limited. There is a possibilty to completely change the UI via MessageBox.setTemplate(), but this affects all MessageBoxes.
In our project, we replaced zk's default MessageBox with our own, which works more like a dialog. With this, we are in full control over the content of the dialog.
public abstract class OurDialog
{
private Window window;
private DialogListener closeListener;
public OurDialog(String title)
{
window = new Window();
window.setTitle(title);
window.setHflex("min");
window.setSizable(false);
window.setPosition("center");
window.setContentStyle("overflow: auto");
window.addEventListener(Events.ON_CLOSE, new EventListener<Event>()
{
#Override
public void onEvent(Event event)
throws Exception
{
if (closeListener != null)
{
if ("confirmed".equals(event.getData()))
{
closeListener.onClose(OurDialog.this);
if (!closeListener.onCloseConfirmation(OurDialog.this))
{
event.stopPropagation();
}
}
else
{
closeListener.onCancel(OurDialog.this);
if (!closeListener.onCancelConfirmation(OurDialog.this))
{
event.stopPropagation();
}
}
}
}
});
}
public final void setWidth(int width)
{
if (width != 0)
{
window.setMinwidth(width);
window.setWidth(width + "px");
}
else
{
window.setHflex("min");
}
}
public final void setHeight(int height)
{
if (height != 0)
{
window.setMinheight(height);
window.setHeight(height + "px");
}
else
{
window.setVflex("min");
}
}
public final void close()
{
Events.sendEvent(Events.ON_CLOSE, window, "confirmed");
}
public final void cancel()
{
Events.sendEvent(Events.ON_CLOSE, window, "cancelled");
}
/**
* #param closeListener called when the dialog is closed.
*/
public final void show(DialogListener closeListener)
{
setCloseListener(closeListener);
window.appendChild(getContent());
GUIHelper.setFocusToFirstInput(window);
OurMeatApplication.getCurrent().showDialog(this);
}
/**
* #return the component to be displayed in the dialog.
*/
protected abstract Component getContent();
}
Our main application class (OurApplication) has a reference to the page and provides the method to show the dialog:
final void showDialog(final OurDialog dialog)
{
Window window = dialog.getWindow();
window.setParent(page);
window.doModal();
}
This is a very generic dialog implementation for pretty much any purpose. For the specific MessageBox case, we have a sub class that provides a prepared UI, error level indicators, several buttons to pick, and a specialised listener to listen to those buttons.
I'm currently developing an Eclipse RCP application, in which I'm trying to implement a custom splash screen handler, sporting a progress bar (behavior similar to the default progress bar you can define in the .product definition) and multiple cycling background images.
After editing the extensions of the main application plugin this way:
[...]
<!-- install custom splash handler -->
<extension point="org.eclipse.ui.splashHandlers">
<splashHandler
class="com.example.application.splash.SlideShowSplashHandler"
id="splash.slideshow">
</splashHandler>
<splashHandlerProductBinding
productId="com.example.application.product"
splashId="com.example.application.splash.slideshow">
</splashHandlerProductBinding>
</extension>
<!-- define images (in plugin root directory) to be shown -->
<extension point="com.example.application.splashExtension">
<splashExtension id="01" image="01_Splash2Ag.bmp"></splashExtension>
<splashExtension id="02" image="02_Splash3Ag.bmp"></splashExtension>
<splashExtension id="00" image="00_Splash1Ag.bmp"></splashExtension>
</extension>
[...]
I'm trying to implement the custom splashscreen handler class:
public class SlideShowSplashHandler extends AbstractSplashHandler {
private List<Image> fImageList;
private ProgressBar fBar;
private final static String F_SPLASH_EXTENSION_ID = "com.example.application.splashExtension"; //NON-NLS-1
private final static String F_ELEMENT_IMAGE = "image"; //NON-NLS-1
private int imageIdx = 0;
public SlideShowSplashHandler() {
fImageList = new ArrayList<Image>(5);
}
/* (non-Javadoc)
* #see org.eclipse.ui.splash.AbstractSplashHandler#init(org.eclipse.swt.widgets.Shell)
*/
public void init(Shell splash) {
// Store the shell
super.init(splash);
// Force shell to inherit the splash background
getSplash().setBackgroundMode(SWT.INHERIT_DEFAULT);
// Load all splash extensions
loadSplashExtensions();
// If no splash extensions were loaded abort the splash handler
if (hasSplashExtensions() == false) return;
// Create UI
createUI(splash);
}
private boolean hasSplashExtensions() {
if (fImageList.isEmpty()) {
return false;
} else {
return true;
}
}
#Override
public IProgressMonitor getBundleProgressMonitor() {
return new NullProgressMonitor() {
#Override
public void beginTask(String name, final int totalWork) {
getSplash().getDisplay().syncExec(new Runnable() {
public void run() {
fBar.setSelection(50);
}
});
}
#Override
public void subTask(String name) {
getSplash().getDisplay().syncExec(new Runnable() {
public void run() {
if (fBar.getSelection() < 100) fBar.setSelection(fBar.getSelection() + 10);
if (imageIdx >= fImageList.size()) imageIdx = 0;
Image image = fImageList.get(imageIdx++);
getSplash().setBackgroundImage(image);
getSplash().setRedraw(true);
getSplash().redraw();
}
});
}
};
}
private void createUI(Shell shell) {
Composite container = new Composite(shell, SWT.NONE);
container.setLayout(new GridLayout(1, false));
container.setLocation(5, 374);
container.setSize(480, 15);
/* Progress Bar */
fBar = new ProgressBar(container, SWT.HORIZONTAL);
fBar.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
((GridData) fBar.getLayoutData()).heightHint = 13;
fBar.setMaximum(100);
fBar.setSelection(25);
/* Version Label */
Label versionLabel = new Label(container, SWT.NONE);
versionLabel.setLayoutData(new GridData(SWT.END, SWT.BEGINNING, true, false));
//versionLabel.setFont(fVersionFont);
//versionLabel.setForeground(fVersionColor);
//versionLabel.setText(NLS.bind(Messages.SplashHandler_BUILD, "2.1 Nightly")); //$NON-NLS-1$
/* Layout All */
shell.layout(true, true);
}
private void loadSplashExtensions() {
// Get all splash handler extensions
IExtension[] extensions = Platform.getExtensionRegistry()
.getExtensionPoint(F_SPLASH_EXTENSION_ID).getExtensions();
// Process all splash handler extensions
for (int i = 0; i < extensions.length; i++) {
processSplashExtension(extensions[i]);
}
}
/**
* Parse the extension points with the images filename.
*/
private void processSplashExtension(IExtension extension) {
// Get all splash handler configuration elements
IConfigurationElement[] elements = extension.getConfigurationElements();
// Process all splash handler configuration elements
for (int j = 0; j < elements.length; j++) {
processSplashElements(elements[j]);
}
}
/**
* Create the images defined as extension points
*/
private void processSplashElements(IConfigurationElement configurationElement) {
String name = configurationElement.getAttribute(F_ELEMENT_IMAGE);
ImageDescriptor descriptor = Activator.getImageDescriptor("/"+name);
if (descriptor != null) {
Image image = descriptor.createImage();
if (image !=null) {
fImageList.add(image);
}
}
}
public void dispose() {
super.dispose();
// Check to see if any images were defined
if ((fImageList == null) ||
fImageList.isEmpty()) {
return;
}
// Dispose of all the images
Iterator<Image> iterator = fImageList.iterator();
while (iterator.hasNext()) {
Image image = iterator.next();
image.dispose();
}
}
}
Problem is that the progress bar just works, while the images are not shown. While debugging I could verify that the images are actually found and loaded, and correctly set in the shell; the shell just seems to not being redrawn. Am i missing something?=
I could solve the problem on linux and windows, but it did not work on macos/cocoa (in which the splash screen is looking "scrambled" on each image slideshow iteration).
Is was very simple indeed, just attaching an extra Composite between the splash shell and the container containing the widgets; then change the background image on the newly create container object.
private void createUI(Shell shell) {
Composite bgcontainer = new Composite(shell, SWT.NONE); // new
[...]
Composite container = new Composite(bgcontainer, SWT.NONE);
[...]
fBar = new ProgressBar(container, SWT.HORIZONTAL);
[...]
Label versionLabel = new Label(container, SWT.NONE);
versionLabel.setLayoutData(new GridData(SWT.END, SWT.BEGINNING, true, false));
shell.layout(true, true);
}
#Override public IProgressMonitor getBundleProgressMonitor() {
return new NullProgressMonitor() {
#Override public void beginTask(String name, final int totalWork) {
getSplash().getDisplay().syncExec(new Runnable() {
public void run() {
if (fBar != null) fBar.setSelection(40);
Image image = fImageList.get(imageIdx++);
bgcontainer.setBackgroundImage(image);
bgcontainer.setRedraw(true);
bgcontainer.update();
}
});
}
#Override public void subTask(String name) {
final String n = name;
getSplash().getDisplay().syncExec(new Runnable() {
String taskname = n;
public void run() {
if (fBar != null && fBar.getSelection() < 100)
fBar.setSelection(fBar.getSelection() + 10);
if (fBar.getSelection() == 60 || fBar.getSelection() == 80) {
if (imageIdx >= fImageList.size()) imageIdx = 0;
Image image = fImageList.get(imageIdx++);
bgcontainer.setBackgroundImage(image);
bgcontainer.setRedraw(true);
bgcontainer.update();
}
}
});
}
};
}
I haven't tried your code, but when you make changes to a Control, it is not enough to call Control.redraw(), but you must also call Control.update().
Control.redraw() requests that a control should be redrawn, Control.update() actually redraws it. The later is needed when your code runs on the UI thread!
I have a barcode scanner and in my java application I have to bring a popup to display all the information associated with the barcode from database when the product is scanned using barcode. I have no textbox on the application I have to handle this part internally. How do I do this ? any suggestion ? I am using swing for UI.
EDIT
Barcode scanner is USB one. If we scan something it will output the result into the textbox which has focus. But I have no textbox working on the page opened. Can i work with some hidden textbox and read the value there ?
Since barcode scanner is just a device which sends keycodes and ENTER after reading of each barcode, I'd use a key listener.
final Frame frame = new Frame();
frame.setVisible(true);
frame.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER) {
// your code is scanned and you can access it using frame.getBarCode()
// now clean the bar code so the next one can be read
frame.setBarCode(new String());
} else {
// some character has been read, append it to your "barcode cache"
frame.setBarCode(frame.getBarCode() + e.getKeyChar());
}
}
});
Since was not able to get input via frame.addKeyListener I have used this utility class which uses KeyboardFocusManager :
public class BarcodeReader {
private static final long THRESHOLD = 100;
private static final int MIN_BARCODE_LENGTH = 8;
public interface BarcodeListener {
void onBarcodeRead(String barcode);
}
private final StringBuffer barcode = new StringBuffer();
private final List<BarcodeListener> listeners = new CopyOnWriteArrayList<BarcodeListener>();
private long lastEventTimeStamp = 0L;
public BarcodeReader() {
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
#Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() != KeyEvent.KEY_RELEASED) {
return false;
}
if (e.getWhen() - lastEventTimeStamp > THRESHOLD) {
barcode.delete(0, barcode.length());
}
lastEventTimeStamp = e.getWhen();
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
if (barcode.length() >= MIN_BARCODE_LENGTH) {
fireBarcode(barcode.toString());
}
barcode.delete(0, barcode.length());
} else {
barcode.append(e.getKeyChar());
}
return false;
}
});
}
protected void fireBarcode(String barcode) {
for (BarcodeListener listener : listeners) {
listener.onBarcodeRead(barcode);
}
}
public void addBarcodeListener(BarcodeListener listener) {
listeners.add(listener);
}
public void removeBarcodeListener(BarcodeListener listener) {
listeners.remove(listener);
}
}
In some way similar to #Cyrusmith solution I have created a 'proof of concept' solution (with several limitations right now, but you are invited to fix them :) ) trying to solve the limitations on the previous solutions in this post:
It support barcode readers that doesn't send the ENTER at the end of barcode string.
If the focus is currently on a swing text component and barcode is captured, the barcode doesn't get to the text component and only to the barcode listener.
See https://stackoverflow.com/a/22084579/320594
I'm doing a Java project which includes little bit of graphical stuffs. I want to display set of BufferedImages under Accordion menu kind of thing. that means when I click on one Accordion menu root item it should display set of images under that name and when clicking on another root menu item it should show another set of images. How could I implement this with Java?. Is there any way to add JPanel as Accordion menu leaf item? If anyone can provide sample code it is really appreciable.
Couldn't resist some fun: turns out that it's possible to tweak a JXTaskPaneContainer (in SwingX) a bit to behave similar to an accordion. All that's needed it to force at most one of the contained JXTaskPaneContainers to be expanded. Something like the code snippet:
JXTaskPaneContainer container = new JXTaskPaneContainer() {
private JXTaskPane current;
private PropertyChangeListener expansionListener;
/**
* #inherited <p>
*/
#Override
protected void addImpl(Component comp, Object constraints, int index) {
super.addImpl(comp, constraints, index);
if (comp instanceof JXTaskPane) {
grabExpansionControl((JXTaskPane) comp);
}
}
private void grabExpansionControl(JXTaskPane comp) {
if (current != null) {
comp.setCollapsed(true);
} else {
current = comp;
comp.setCollapsed(false);
}
comp.addPropertyChangeListener("collapsed",
getExpansionListener());
}
private void updateCurrentTaskPane(JXTaskPane source) {
if (source != current) {
if (!source.isCollapsed()) {
if (current != null) {
current.setCollapsed(true);
}
current = source;
}
}
}
private PropertyChangeListener createExpansionListener() {
PropertyChangeListener l = new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
// TODO Auto-generated method stub
updateCurrentTaskPane((JXTaskPane) evt.getSource());
}
};
return l;
}
private PropertyChangeListener getExpansionListener() {
if (expansionListener == null) {
expansionListener = createExpansionListener();
}
return expansionListener;
}
};
((VerticalLayout) container.getLayout()).setGap(0);
Well a little bit of googling and I found this link .
It may be helpful for you -
http://code.google.com/p/martin-personal-project/downloads/detail?name=SwingAccordionMenu.zip&can=2&q=
You will get a ZIP file , unzip and run the SwingAccordionMenu.jar, you will get accordion as output like -