hi i am newbie to blackberry.i will be having two buttons one for addition of rows and other for deletion of rows.
|--------------------------------------------|
||----------------------------------||------||
||labelfield ||Bitmap||
||__________________________________||______||
|____________________________________________|
|--------------------------------------------|
| Editfield |
|--------------------------------------------|
Above is customized view of datepicker,Where on click of bitmap datepicker popups to choose date and that date value get binded to edit field,this is contained in one row and other row contains an edit field which allows to enter amount which shall be formatted as user enter's numerals.
Initially two default row will be present to choose date and enter amount.On click of add button these two rows shall be added.and these rows values will be retrieved whenever required.
similarly on click of deletion button these two rows will get deleted.If user has to add next two rows the previous rows must be filled.
the code i have used for datepicker is given below
VerticalFieldManager datevertfield = new VerticalFieldManager();
String pattern = "MM/dd/yyyy";
String dateInString = new SimpleDateFormat(pattern).format(new Date());
LabelField lblcal1 = new LabelField("Date", DrawStyle.LEFT
| Field.FIELD_LEFT) {
public void paint(Graphics g) {
g.setColor(0xffffff);
super.paint(g);
}
};
datevertfield.add(lblcal1);
HorizontalFieldManager datepickerHoriztalField = new HorizontalFieldManager();
HorizontalFieldManager dateHoriztalField = new HorizontalFieldManager()
{
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(Display.getWidth() - horiwidth, horiheight);
setExtent(Display.getWidth() - horiwidth, horiheight);
}
};
XYEdges xyEdge1 = new XYEdges(border, border, border, border);
XYEdges xyEdgeColors1 = new XYEdges(0x2AACFF, 0x2AACFF, 0x2AACFF,
0x2AACFF);
Border aBorder1 = BorderFactory.createSimpleBorder(xyEdge1,
xyEdgeColors1, Border.STYLE_SOLID);
dateHoriztalField.setBorder(aBorder1);
datepickerHoriztalField.add(dateHoriztalField);
BitmapField iconimg = new BitmapField(
GPATools.ResizeTransparentBitmap(
Bitmap.getBitmapResource("Calender.png"),
imgwidth, imgheight, Bitmap.FILTER_LANCZOS,
Bitmap.SCALE_TO_FIT), Field.FOCUSABLE) {
protected boolean navigationClick(int status, int time) {
try {
DateTimePicker datePicker = DateTimePicker.createInstance();
datePicker.doModal();
Calendar cal = datePicker.getDateTime();
datePicker.setMaximumDate(cal.getInstance());
Date curtime = cal.getTime();
DateFormat formattertime = new SimpleDateFormat(
"MM/dd/yyyy");
String currentTime = formattertime.format(curtime);
txtpickdate.setText(currentTime);
} catch (Exception e) {
}
return true;
}
};
txtpickdate = new LabelField("Enter Date", DrawStyle.LEFT
| Field.FIELD_LEFT) {
protected void paint(Graphics g) {
g.setColor(Color.WHITE);
super.paint(g);
}
};
dateHoriztalField.add(txtpickdate);
datepickerHoriztalField.add(iconimg);
datevertfield.add(datepickerHoriztalField);
add(datevertfield);
This is code used for date picker row like this i want to add datepiker row and next edit field row on click of butn .and this could be deleted on click of delete btn.
In this i need to know how to add and delete these rows and how to know whether user has entered previous Date and edit field row to do validation.
Could anyone give me idea on how to start with this.Code example will be appreciated.
I'm not sure if I understood the question or not, but from what I understand you are looking for:
A label & Button to select date
EditField restricted to numerical text
Button to create a field from a date and number
Created Fields can be deleted
I created a smallish example for doing this. I did not include the number restriction on the text field, but the rest should be a decent base to start from. I would recommend not using a BitmapField as a button because it won't be good for ux. You'll likely want a field with images for each state (none, focused, pressed)
public final class MyScreen extends MainScreen
{
private Calendar calendar;
private LabelField labelField;
private BitmapField bitmapField;
private EditField editField;
private SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
public MyScreen()
{
super(NO_HORIZONTAL_SCROLL);
// ----- TODO ------
// Too lazy to include a bmp, so I generated one. You should replace this with your icon
Bitmap bmp = new Bitmap(50, 50);
Graphics g = Graphics.create(bmp);
g.setColor(0xEFEFEF);
g.fillRect(0, 0, bmp.getWidth(), bmp.getHeight());
// ------------------
bitmapField = new BitmapField(bmp, FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
if (calendar == null)
{
calendar = Calendar.getInstance();
}
DateTimePicker datePicker = DateTimePicker.createInstance(calendar);
datePicker.doModal();
calendar = datePicker.getDateTime();
if (calendar == null)
{
labelField.setText("null"); // Your error message here
}
else
{
labelField.setText(formatter.format(calendar.getTime()));
}
return true;
}
};
labelField = new LabelField(null, USE_ALL_WIDTH) // Tell labelField to use as much width as possible
{
protected void layout(int width, int height)
{
// Layout the label as though less space is available (to fit the bitmap button in)
super.layout(width - bitmapField.getBitmapWidth(), height);
}
};
HorizontalFieldManager manager = new HorizontalFieldManager(USE_ALL_WIDTH);
add(manager);
manager.add(labelField);
manager.add(bitmapField);
editField = new EditField(USE_ALL_WIDTH);
add(editField);
ButtonField addButton = new ButtonField("ADD")
{
protected boolean navigationClick(int status, int time)
{
String text = editField.getText();
if ((calendar != null) && (text != null) && (text.length() > 0))
{
add(new EntryField(calendar.getTime(), text));
}
else
{
// TODO notify invalid data?
}
return true;
}
};
add(addButton);
}
public class EntryField extends HorizontalFieldManager
{
public EntryField(Date date, String text)
{
super(USE_ALL_WIDTH);
// ----- TODO ------
// Too lazy to include a bmp, so I generated one. You should replace this with your icon
Bitmap bmp = new Bitmap(50, 50);
Graphics g = Graphics.create(bmp);
g.setColor(0xFF0000);
g.fillRect(0, 0, bmp.getWidth(), bmp.getHeight());
// ------------------
final BitmapField bitmapField = new BitmapField(bmp, FOCUSABLE)
{
protected boolean navigationClick(int status, int time)
{
EntryField.this.getManager().delete(EntryField.this); // Remove this field from its parent
// Depending on what kind of interactions this field exposes, this will most likely need to make use of a callback instead.
return true;
}
};
final LabelField labelField = new LabelField(formatter.format(date) + " - " + text, USE_ALL_WIDTH) // Tell labelField to use as much width as possible
{
protected void layout(int width, int height)
{
// Layout the label as though less space is available (to fit the bitmap button in)
super.layout(width - bitmapField.getBitmapWidth(), height);
}
};
add(labelField);
add(bitmapField);
}
}
}
Related
On most systems, the content in my JLabel just shows fine. It is also resided in a way that it should be always big enough to show its content text because I basically do this:
label.setText(text);
label.setFont(new Font(fontName, 0, 12));
int width = label.getFontMetrics(label.getFont()).stringWidth(text);
int height = 21; // this should always be enough
label.setBounds(new Rectangle(x, y, width, height));
But on some systems (not my own so I cannot really debug it that easy), it cuts the text and shows "..." at the end.
You can see the full code here and you can see the example here (Abbildungen_Bijektiv_X3).
I also have some similar case for JButton.
How can I force Swing to not do that? (Even if it thinks that the component is too small.)
Where exactly does Swing handle this? I browsed through the code of JButton and some related classes but I didn't really found the code where it cuts the text and adds the ellipsis.
There should be no need to set the bounds of the label.
That is the job of a layout manager. Learn to use layout managers and you won't have this problem.
Edit:
Layout managers use:
label.setSize( label.getPreferredSize() );
I am doing this now (for buttons but you could do it in a similar way for other controls):
static public class ButtonUI extends MetalButtonUI {
public static ComponentUI createUI(JComponent c) {
return new ButtonUI();
}
#Override public void paint(Graphics g, JComponent c) {
JSimpleLabel.activateAntiAliasing(g);
AbstractButton b = (AbstractButton) c;
ButtonModel model = b.getModel();
String text = b.getText();
clearTextShiftOffset();
// perform UI specific press action, e.g. Windows L&F shifts text
if (model.isArmed() && model.isPressed()) {
paintButtonPressed(g,b);
}
FontMetrics metrics = g.getFontMetrics();
Rectangle2D stringBounds = metrics.getStringBounds(text, g);
g.drawString(text,
(b.getWidth() - (int)stringBounds.getWidth()) / 2,
metrics.getLeading() + metrics.getMaxAscent() + (b.getHeight() - (int)stringBounds.getHeight()) / 2);
if (b.isFocusPainted() && b.hasFocus()) {
Rectangle viewRect = new Rectangle();
final int inset = 1;
viewRect.x = inset;
viewRect.y = inset;
viewRect.width = b.getWidth() - (inset + viewRect.x) - 1;
viewRect.height = b.getHeight() - (inset + viewRect.y) - 1;
g.setColor(getFocusColor());
g.drawRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height);
}
}
}
public void init() {
try {
UIManager.setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel() {
private static final long serialVersionUID = 1L;
#Override public UIDefaults getDefaults() {
UIDefaults table = super.getDefaults();
table.put("ButtonUI", ButtonUI.class.getName());
return table;
}
});
} catch (Exception e) {
e.printStackTrace();
}
// ...
}
You could use a cross platform look and feel (Like Nimbus) to stop this occuring
I am coding a little Plugin for Eclipse (using SWT), which creates a view with a couple of buttons. In order not to produce redundant code I want to create some kind of factory method to create my buttons for me. The call would be something like:
Button button0 = createButton(new Button(parent, SWT.PUSH), "Test DB zurücksetzen", btnHight, btnWidth, new FormAttachment(0, 2), new FormAttachment(0,2));
My factory, so far, looks like this:
private Button createButton(Button buttonToCreate, String buttonText, int height, int width, FormAttachment left, FormAttachment top) {
buttonToCreate.setText(buttonText);
FormData formData = new FormData();
formData.height = height;
formData.width = width;
formData.left = left;
formData.top = top;
buttonToCreate.setLayoutData(formData);
buttonToCreate.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
Actions.editPropertys();
}
});
return buttonToCreate;
}
My Question is: How can I pass the Method of the Actions class I want to execute to the factory as a parameter?
You could convey it as a Runnable parameter of the method.
For example :
private Button createButton(Button buttonToCreate, String buttonText, int height, int width, FormAttachment left, FormAttachment top, Runnable actionOnSelection) {
// ...
buttonToCreate.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
actionOnSelection.run(); // change here
}
});
}
and invoke it :
Button button0 = createButton(new Button(parent, SWT.PUSH), "Test DB zurücksetzen", btnHight, btnWidth, new FormAttachment(0, 2), new FormAttachment(0,2),
Actions::editPropertys); // other change here
I'm playing around with Android MP Chart lib to draw awesome charts.
I'm trying to highlight values on my chart, but it does not puts the highlight to the right place, or throws ArrayIndexOutOfBoundsException.
I've made a little dummy project for it. When user clicks on the next button, the highlight should move to positive direction.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
final int DATA_MAX_COUNT = 30;
List<MyData> list = new ArrayList<>(); ///<Dummy data stored in here
List<Entry> entries = new ArrayList<>(); ///<Entries for MP Chart
int highlightIndex = 0; ///<Chart's data index to be highlighted
CombinedChart combinedChart; ///<I use combined chart because there will be more data sets added later on
Button prevBtn; ///<Button for highlight control
Button nextBtn; ///<Button for highlight control
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
combinedChart = (CombinedChart) findViewById(R.id.chart);
prevBtn = (Button) findViewById(R.id.prev_btn);
prevBtn.setOnClickListener(this);
nextBtn = (Button) findViewById(R.id.next_btn);
nextBtn.setOnClickListener(this);
generateData();
drawChart();
}
#Override
public void onClick(View v) {
//Clicking buttons should move the highlighted value
if (v.equals(prevBtn)) {
if (highlightIndex > 0) {
highlightIndex--;
}
} else if (v.equals(nextBtn)) {
if (highlightIndex + 1 < DATA_MAX_COUNT) {
highlightIndex++;
}
}
//Does not work, throws exception
//combinedChart.highlightValue(new Highlight(highlightIndex, 0, 0));
//Does not work, throws exception
//combinedChart.highlightValue(highlightIndex, 0, false);
//Exception
// java.lang.ArrayIndexOutOfBoundsException: length=10; index=-1
// at com.github.mikephil.charting.data.CombinedData.getDataByIndex(CombinedData.java:152)
// at com.github.mikephil.charting.data.CombinedData.getEntryForHighlight(CombinedData.java:183)
// at com.github.mikephil.charting.charts.Chart.highlightValue(Chart.java:635)
// at com.github.mikephil.charting.charts.Chart.highlightValue(Chart.java:613)
//Works, but highlights value on chart with like x=0 and y= 190, wtf?
combinedChart.highlightValue(combinedChart.getHighlighter().getHighlight(highlightIndex, 0));
}
//Generating random data to a list
public void generateData() {
for (int i = 0; i < DATA_MAX_COUNT; i++) {
MyData myData = new MyData(new Random().nextInt(100) + 100);
list.add(myData);
}
}
//Simple func for adding data to entries and drawing chart
private void drawChart() {
CombinedData combinedData = new CombinedData();
for (int i = 0; i < list.size(); i++) {
MyData myData = list.get(i);
entries.add(new Entry(i, myData.getValue(), myData));
}
LineDataSet lineDataSet = new LineDataSet(entries, "My data list");
lineDataSet.setHighLightColor(Color.RED);
lineDataSet.setHighlightLineWidth(3);
LineData lineData = new LineData();
lineData.addDataSet(lineDataSet);
combinedData.setData(lineData);
combinedChart.setData(combinedData);
combinedChart.invalidate();
}
//Dummy data class
public static class MyData {
private int value;
public MyData(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
}
I don't get it why I'm getting
java.lang.ArrayIndexOutOfBoundsException: length=10; index=-1
Because what the hell is -1? and what is 10? There are not a single thing in my code which is 10, and why does any of the chart's functions getting -1?
I'm using
com.github.PhilJay:MPAndroidChart:v3.0.3
Please help if you can.
E D I T:
I've added combinedChart.setOnChartValueSelectedListener(this); to the chart.
With this callback onValueSelected(Entry, Highlight) I can test this thing in another way. It gives a Highlight object. If I does nothing in this callback, the chart draws the highlights well. If I call it programatically with the same X value, it throws the usual exception or draws the highlight to wrong position. (to zero)
See the callback:
#Override
public void onValueSelected(Entry e, Highlight h) {
float x = h.getX();
Log.i("Highlighted", "Actual highlight: " + x);
//Getting the same exception as above
//combinedChart.highlightValue(x, 0, false);
//Does not works, draws to x=0 position with any given x
combinedChart.highlightValue(combinedChart.getHighlighter().getHighlight(x, 0));
}
Here is solution:
Highlight high = new Highlight(highlightIndex, 0, 0);
high.setDataIndex(0);
combinedChart.highlightValue(high, false);
You need to add high.setDataIndex(0); line.
Explaination:
In Highlight constructor first parameter is X value, the value you increase or decrease. Second is index of graph you want to select. Since you have only one, you specify 0 there. Also you should specify it second time high.setDataIndex(0); (otherwise it is treated as -1, bug ! ) and your code will work:
Bit of an odd one, I'm using JavaFX 8 and am having some odd behaviour I picked up during my Jubula testing.
I have a datepicker control that is created with the following code:
public DatePicker getDatePicker(DtDate defaultDate, int width){
DatePicker dtpckr = new DatePicker();
dtpckr.setMaxWidth(width);
dtpckr.setMinWidth(width);
dtpckr.setConverter(new StringConverter<LocalDate>() {
private DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("yyyy/MM/dd");
#Override
public String toString(LocalDate localDate) {
if(localDate==null)
return "";
return dateTimeFormatter.format(localDate);
}
#Override
public LocalDate fromString(String dateString) {
if(dateString==null || dateString.trim().isEmpty())
return null;
return LocalDate.parse(dateString,dateTimeFormatter);
}
});
dtpckr.setPromptText("yyyy/MM/dd");
dtpckr.setValue(LocalDate.parse(defaultDate.toString(), DateTimeFormatter.ofPattern("yyyy/MM/dd")));
return dtpckr;
}
That works fine and the control is created on the form and works as expected. If I use the calendar to pick the date, the value is updated.
Now, for the odd part, if I enter in the datepicker and manually type the date in (E.g. 2017/10/11) and then exit the control by either tabbing or clicking on the next textbox on the form, the datepicker localdate value doesn't get updated. The only method to update the date would be to press enter to force the datepicker to realise a new value is present. This causes another problem as I have the following code:
public void createSetDateAndTimeControls(){
DtDateAndTime currentDateAndTime;
try {
currentDateAndTime = systemstateController.getServerDateTime();
/*
* Creating controls to be used on the form
*/
int width = 150;
DatePicker dtpckr = getDatePicker(currentDateAndTime.date, width);
Label lblDate = new Label("Date:");
Label lblTimeHour = new Label("Hour:");
Label lblTimeMinute = new Label("Minute:");
Label lblTimeSecond = new Label("Second:");
TextField txtfldCurrentSetSecond = new TextField();
TextField txtfldCurrentSetMinute = new TextField();
TextField txtfldCurrentSetHour = new TextField();
Slider sldrHourPicker = getSlider(width, SliderType.Hour, txtfldCurrentSetHour, currentDateAndTime.time);
Slider sldrMinutePicker = getSlider(width, SliderType.Minute, txtfldCurrentSetMinute, currentDateAndTime.time);
Slider sldrSecondPicker = getSlider(width, SliderType.Second, txtfldCurrentSetSecond, currentDateAndTime.time);
/*
* Adding a grid pane to keep controls in correct place and aligned correctly
*/
GridPane grdpn = new GridPane();
grdpn.add(lblDate, 1, 1);
grdpn.add(dtpckr, 2, 1, 2,1);
grdpn.add(lblTimeHour, 1, 2);
grdpn.add(sldrHourPicker, 2, 2, 2 ,1);
grdpn.add(txtfldCurrentSetHour, 4, 2);
grdpn.add(lblTimeMinute, 1, 3);
grdpn.add(sldrMinutePicker, 2, 3, 2, 1);
grdpn.add(txtfldCurrentSetMinute, 4, 3);
grdpn.add(lblTimeSecond, 1, 4);
grdpn.add(sldrSecondPicker, 2, 4, 2, 1);
grdpn.add(txtfldCurrentSetSecond, 4, 4);
/*
* Creating buttons for user to press
*/
Button bttnOK = new Button("Change date and time");
bttnOK.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
try {
if (checkIfAllDialogHasBeenFilledIn(grdpn)){
LocalDate test = dtpckr.getValue();
if (systemstateController.oeSetClock(ICrashUtils.setDateAndTime(dtpckr.getValue().getYear(), dtpckr.getValue().getMonthValue(), dtpckr.getValue().getDayOfMonth(),
(int)Math.floor(sldrHourPicker.getValue()), (int)Math.floor(sldrMinutePicker.getValue()), (int)Math.floor(sldrSecondPicker.getValue()))).getValue())
showOKMessage("Updated", "Date and time was updated successfully");
else
showErrorMessage("Error", "There was an error updating the date and time");
}
else
showUserCancelledActionPopup();
} catch (ServerOfflineException | ServerNotBoundException e) {
showExceptionErrorMessage(e);
}
}
});
bttnOK.setDefaultButton(true);
grdpn.add(bttnOK, 2, 5, 3, 1);
Button bttnSetNow = new Button("Now");
bttnSetNow.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
dtpckr.setValue(LocalDate.now());
LocalTime time = LocalTime.now();
sldrHourPicker.setValue(time.getHour());
sldrMinutePicker.setValue(time.getMinute());
sldrSecondPicker.setValue(time.getSecond());
}
});
grdpn.add(bttnSetNow, 4, 1);
/*
* End of creating controls to be used on the form
*/
anchrpnActivator.getChildren().add(grdpn);
AnchorPane.setTopAnchor(grdpn, 0.0);
AnchorPane.setRightAnchor(grdpn, 0.0);
AnchorPane.setLeftAnchor(grdpn, 0.0);
AnchorPane.setBottomAnchor(grdpn, 0.0);
} catch (ServerOfflineException | ServerNotBoundException e) {
showExceptionErrorMessage(e);
}
}
Which has the following line:
bttnOK.setDefaultButton(true);
This means that if a user presses enter during the text entry on the date picker control, it fires off the onaction event, before the user has put in data in the other controls, and I don't particularly want that.
So the question is, why doesn't the dtpckr.getValue() change if a user enters text into the box and then leaves the box without pressing enter? I can't find an event to call on user leaving the datepicker box or a property of the datepicker to get the text value of the control and compare it to the value of dtpckr.getValue(). Is there something that I'm missing here?
Let me know if you need more information!
[Edit]
It appears this might be a bug in the current datepicker setup in JavaFX
I might have to remove the default button and put in an enter press in the Jubula test to make this work properly. Unless someone has an alternative?
The bug log that I added above had the answer. You can access the string value of the textbox via this code:
datePicker.getEditor().getText();
So setting the textbox value can be done via:
datePicker.setValue(datePicker.getConverter()
.fromString(datePicker.getEditor().getText()));
I'm adding an event to the lost focus event, that will force the datepicker value to be updated
And the working code:
public DatePicker getDatePicker(DtDate defaultDate, int width){
DatePicker dtpckr = new DatePicker();
dtpckr.setMaxWidth(width);
dtpckr.setMinWidth(width);
dtpckr.setConverter(new StringConverter<LocalDate>() {
private DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("yyyy/MM/dd");
#Override
public String toString(LocalDate localDate) {
if(localDate==null)
return "";
return dateTimeFormatter.format(localDate);
}
#Override
public LocalDate fromString(String dateString) {
if(dateString==null || dateString.trim().isEmpty())
return null;
try{
return LocalDate.parse(dateString,dateTimeFormatter);
}
catch(Exception e){
//Bad date value entered
return null;
}
}
});
dtpckr.setPromptText("yyyy/MM/dd");
dtpckr.setValue(LocalDate.parse(defaultDate.toString(), DateTimeFormatter.ofPattern("yyyy/MM/dd")));
//This deals with the bug located here where the datepicker value is not updated on focus lost
//https://bugs.openjdk.java.net/browse/JDK-8092295?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
dtpckr.focusedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (!newValue){
dtpckr.setValue(dtpckr.getConverter().fromString(dtpckr.getEditor().getText()));
}
}
});
return dtpckr;
}
#Draken's answer needs a little extra. If the user types an invalid date the code will throw a DateTimeParseException. You can emulate the DatePicker's own behaviour thus:
dtpckr.getEditor().focusedProperty().addListener((obj, wasFocused, isFocused)->{
if (!isFocused) {
try {
dtpckr.setValue(dtpckr.getConverter().fromString(dtpckr.getEditor().getText()));
} catch (DateTimeParseException e) {
dtpckr.getEditor().setText(dtpckr.getConverter().toString(dtpckr.getValue()));
}
}
});
I recently fixed this issue in the newest JavaFX version: https://github.com/openjdk/jfx/pull/679
So when JavaFX 18-ea+9 will be released you can use it and remove the workaround. :-)
I had the same problem. Did this trick to solve it:
Date date = DateConverter.toDate(datePicker.getEditor().getText());
where DateConverter.toDate() is a method that converts the string to date.
I know it’s a little off topic, but for a while I had users who didn’t press ENTER to submit, so I did this.
/**
* This will automatically submit the input on lost of focus, if it's typed but not submitted (with ENTER).
*
* #param picker to apply
*/
private void activateAutoSubmit(DatePicker picker) {
// On Focus Leave Listener
picker.focusedProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue) {
try {
// Set typed text to DatePicker value
picker.setValue(picker.getConverter().fromString(picker.getEditor().getText()));
} catch (Exception e) {
// For wrong input return old value
picker.getEditor().setText(picker.getConverter().toString(picker.getValue()));
}
}
});
}
Usage
#FXML
private DatePicker dateStart;
#FXML
private DatePicker dateEnd;
#FXML
private void initialize() {
...
activateAutoSubmit(dateStart);
activateAutoSubmit(dateEnd);
...
}
I'm currently trying to add some images from a decoded video to a TableView row and they are not appearing. Only empty TableColumns. The TableView has been designed in JavaFx Scene Builder along with the Label.
Here's what I got so far:
public class MainScreenController implements Initializable {
#FXML
private Label previewBoxLabel;
#FXML
private TableView tableView;
private ObservableList<ImageView> imageList = FXCollections.observableArrayList();
#FXML
public void AddClipBeta(){
//Code which uses an external class in order to decode video (Variables Frames, width and height are not shown but are present in the actual code)
VideoSegment clip = new VideoSegment(0, file.getPath(), 0, Frames, width, height);
//Opens the file in decoding class - ready to output frames
try{clip.openFile();} catch(Exception e){}
//First frame is updated on the preview box
previewBoxLabel.setGraphic(new ImageView(convertToFxImage(clip.getThumbnail())));
System.out.println(file.getPath());
int i =0;
//While loop in test phase to see whether or not 10 frames will be visible in the table
while(i != 10){
//Creates and sets columns to tableView
TableColumn<ImageView, ImageView> col = new TableColumn<ImageView, ImageView>();
col.setPrefWidth(100); //Set width of column
tableView.getColumns().add(col);
col.setCellFactory(new Callback<TableColumn<ImageView, ImageView>, TableCell<ImageView, ImageView>>() {
#Override
public TableCell<ImageView, ImageView> call(TableColumn<ImageView, ImageView> p) {
TableCell<ImageView, ImageView> cell = new TableCell<ImageView, ImageView>(){
};
return cell;
}
});
//Adds current frame to list
imageList.add(new ImageView(convertToFxImage(clip.getThumbnail())));
//Gets next video frame
try{clip.getNextFrame();} catch(Exception e){}
//Updates counter
i++;
}
//Sets list of frames on the table
tableView.setItems(imageList);
}
// There is a problem with this implementation: transparent pixels on the BufferedImage aren't converted to transparent pixels on the fxImage.
public static javafx.scene.image.Image convertToFxImage(java.awt.image.BufferedImage awtImage) {
if (Image.impl_isExternalFormatSupported(BufferedImage.class)) {
return javafx.scene.image.Image.impl_fromExternalImage(awtImage);
} else {
return null;
}
}
I've been struggling understanding how the TableView works the last couple of days and it would be a real breakthrough if we could get to the bottom of this.
Thanks for reading and any help in advance!
When setting a CellFactory, you need to take in to account that it will override some default bevaiours such as setting text and images.
For example. I had to create a ListView of Applications that launched on double click. I had to set a CellFactory in order to add a listener to the mouse click of each individual cell.
applications.setCellFactory(new Callback<TreeView<Application>, TreeCell<Application>>() {
#Override
public TreeCell<Application> call(TreeView<Application> param) {
return new TreeCell<Application>() {
#Override
protected void updateItem(Application item, boolean empty) {
//call the origional update first
super.updateItem(item, empty);
//the root item in my list is null, this check is required to keep a null pointer from happening
if (item != null) {
// text and graphic are stored in the Application object and set.
this.setText(item.getApplicationListName());
this.setGraphic(item.getGraphic());
// registers the mouse event to the cell.
this.setOnMouseClicked((MouseEvent e) -> {
if (e.getClickCount() == 2) {
try {
this.getItem().launch(tabBar);
} catch (UnsupportedOperationException ex) {
Dialogs.create().nativeTitleBar().masthead("Comming Soon™").message("Application is still in development and will be available Soon™").nativeTitleBar().title("Unavailable").showInformation();
}
} else {
e.consume();
}
});
}else if(empty){
this.setText(null);
this.setGraphic(null);
this.setOnMouseClicked(null);
}
}
};
}
});
This was pieced together from some other code so if there is anything else you would like explained, let me know!
I managed to sort this out with the help of you guys. Basically, what I did was make a class with a bunch of setters and getters and a constructor that takes in ImageViews and sets it to a variable in the class via it's constructors. Then I went back to my code and added the following:
Class with Getters and Setters:
import javafx.scene.image.ImageView;
public class tableDataModel {
private ImageView image;
public tableDataModel(ImageView image){
this.image = image;
}
public ImageView getImage(){
return image;
}
public void setImage(ImageView image){
this.image = image;
}
}
Code from MainScreenController:
TableColumn<tableDataModel, ImageView> col = new TableColumn<>();
tableView.getColumns().add(col);
imageList.add(new tableDataModel(new ImageView(convertToFxImage(clip.getThumbnail()))));
col.setPrefWidth(50);
col.setCellValueFactory(new PropertyValueFactory<tableDataModel, ImageView>("image"));
int i = 0;
while (i != 10) {
try {
imageList.add(new tableDataModel(new ImageView(convertToFxImage(clip.getNextFrame()))));
} catch (Exception e) {
}
i++;
}
tableView.setItems(imageList);