is there any thing got changed for images. Circular button shows different with projections. Button use to display proper circle before. Please see the screenshots for reference. Please advise.
Button b;
Button finished = new Button("");
FontImage.setMaterialIcon(finished, FontImage.MATERIAL_CHECK, 8.0f);
Test.makeBorderRound(finished);
Style bg = finished.getDisabledStyle();
finished.setDisabledStyle(bg);
b = finished;
b.setDisabledStyle(bg);
public static void makeBorderRound(Component cmp) {
makeBorderRound(cmp.getUnselectedStyle());
makeBorderRound(cmp.getSelectedStyle());
makeBorderRound(cmp.getPressedStyle());
makeBorderRound(cmp.getDisabledStyle());
}
public static void makeBorderRound(Style stl) {
stl.setBorder(RoundBorder.create().
rectangle(true).
color(stl.getBgColor()).
opacity(stl.getBgTransparency() & 0xff));
stl.setPaddingUnit(Style.UNIT_TYPE_DIPS);
stl.setPaddingLeft(1);
stl.setPaddingRight(1);
}
That's the icon peaking out from the edges of the round border. We fixed a bug where the background wasn't painted for some cases.
A simple workaround would be:
Button finished = new Button("");
finished.getAllStyles().setBgTransparency(0);
FontImage.setMaterialIcon(finished, FontImage.MATERIAL_CHECK, 8.0f);
finished.getAllStyles().setBgTransparency(255);
Test.makeBorderRound(finished);
By setting the bg transparency to 0 the icon will have transparency, this will then get overwritten by the second line after the icons are created.
Related
Simple problem.
I have a form to which I add a panel and put 1 label with some text. When I look at the saved image, all I see is the panel. I have tried all the solutions I could find. Code below. I get the panel saved but the text box doesn't appear. If I can get that to work, then I can do all that I need.
What am I doing wrong?
int x = SystemInformation.WorkingArea.X;
int y = SystemInformation.WorkingArea.Y;
int width = printPanel.Width;
int height = printPanel.Height;
Rectangle bounds = new Rectangle(x, y, width, height);
using (Bitmap flag = new Bitmap(width, height))
{
printPanel.DrawToBitmap(flag, bounds);
if (Environment.UserName == "grimesr")
{
string saveImage = Path.Combine(fileStore, "./p" + ".png");
flag.Save(saveImage);
}
}
Really not sure where you're going wrong.
Here's a simple test:
private void button1_Click(object sender, EventArgs e)
{
int width = printPanel.Width;
int height = printPanel.Height;
Rectangle bounds = new Rectangle(0, 0, width, height);
Bitmap flag = new Bitmap(width, height);
printPanel.DrawToBitmap(flag, bounds);
pictureBox1.Image = flag;
}
It grabs the entire panel and puts the image into the picturebox to the right:
Thanks for the hints, even if they weren't directly related. The print button helped me figure this out. The button code worked as desired. However, putting the same code where I had it wasn't working. I then noticed a InvalidOperation error was being rasied. So looking at more in detail led me to see what the real issue was.
I must admit I left out 1 tiny piece of information that was critical. I was trying to do this in a thread that was feeding my label printer. Of course, trying to used a UI panel control in the thread threw an Invalid Operation. I moved the code out and all is well now. Cross thread operations are sometimes subtle and difficult to think about how they fail.
Problem solved for me.
We have a GTK3 user interface (coded in C) in an embedded system that must stay fixed width/height in order to fit the screen.
Basically it's a fixed grid of buttons on a touchscreen, where the buttons can contain a text label or a graphical image - and the grid MUST stay fixed, all buttons the same width & height, and fitting the screen 100%.
However, on updating button text/labels with longer strings the button expands to fit which is not what we want at all.
I can't post all the code but I believe this is the relevant button creation code that would affect what we're trying to do;
// Number buttons 1..n
buttonId = n;
bid = buttonId - 1; // Because zero-indexing, natch
dbp = &_context->buttons[bid]; // Data about button
// Create new button, attach to global buttons
dbp->btn = gtk_button_new();
// Button name != Button CSS#ID
snprintf(value, SHORT_STR, "BTN_%02d", buttonId );
gtk_widget_set_name(dbp->btn, value);
gtk_button_set_relief(GTK_BUTTON(dbp->btn), GTK_RELIEF_NORMAL/*GTK_RELIEF_NONE*/);
// Set text label
strncpy(dbp->text, value, MAX_BUTTON_TEXT);
gtk_button_set_label (GTK_BUTTON(dbp->btn), dbp->text);
// Attempt to make labels wrap - does nothing
label = gtk_bin_get_child(GTK_BIN(dbp->btn));
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
//gtk_label_set_max_width_chars(GTK_LABEL(label), 0);
// Create new blank (&transprent) image
dbp->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, _context->innerButton.width, _conte$
gdk_pixbuf_fill(dbp->pixbuf, 0x00000000);
// Image holds pixbuf
dbp->image = (GtkImage*)gtk_image_new_from_pixbuf(dbp->pixbuf);
dbp->image_modified = 0;
// Attach image to button
gtk_button_set_image(GTK_BUTTON(dbp->btn), GTK_WIDGET(dbp->image));
// Adds an individual CSS provider per button to allow style changes
GtkStyleContext *context = gtk_widget_get_style_context(dbp->btn);
dbp->bp = gtk_css_provider_new();
// Set default colour from table of default colours
dbp->bg = get_default_colour(bid);
dbp->fg = get_label_colour(dbp->bg);
BuildButtonCSS("btnid_", buttonId, dbp->bg, dbp->fg, tstr, NULL);
// Convert CSS to provider
gtk_css_provider_load_from_data(dbp->bp, tstr, -1, NULL);
// Add provider to button
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER(dbp->bp), GTK_STYLE_PROVIDER_PRIO$
// Give the button the CSS style/class corresponding to the one we just created for it
snprintf(value, SHORT_STR, "btnid_%02d", buttonId);
gtk_style_context_add_class(context, value);
g_object_unref(dbp->bp);
// Discourage expansion (again, doesn't appear to work when label gets too long)
gtk_widget_set_hexpand(dbp->btn, FALSE);
gtk_widget_set_vexpand(dbp->btn, FALSE);
// Attach button to grid
gtk_grid_attach(GTK_GRID(_grid), dbp->btn, c, r, 1, 1);
g_signal_connect(dbp->btn, "button_press_event", G_CALLBACK(button_press_callback), GINT_TO_P$
g_signal_connect(dbp->btn, "button_release_event", G_CALLBACK(button_release_callback), GINT_$
dbp->initialised = 1;
However when we update text within a button, it renders as a single (non-wrapped) line of text and causes the button to expand and totally bu&&er up the layout.
There's two problems here;
The text should wrap, the buttons have plenty of height but the text remains a single line
The buttons should be absoltuely FIXED width & height no matter what
This feels like it should be simple to do, but I'm not very familiar with GTK and all the examples out there seem to assume that you'd want everything to flex and resize itself all the time.
Edit: Tried Alexander Dmitriev's suggestion to use ellipsize - didn't seem to work although threw no errors;
// Experiment; ellipsize
label = gtk_bin_get_child(GTK_BIN(dbp->btn));
gtk_label_set_ellipsize(GTK_LABEL(label),PANGO_ELLIPSIZE_END);
gtk_label_set_max_width_chars(GTK_LABEL(label), 14);
I also tried this exmaple by creating a GtkWidget label, applying the properties to it and then adding it to the button - but it seems gtk_button_set_label will only accept a string not a label.
I have an array of horizontal fields which contains a bitmap and a labelfield each. The whole row should be clickable which is working so far, but how can I set the focus color properly? At the moment the onFocus and onUnfocus functions are being completely ignored.
This is the definition of my array:
for (int i = 0; i < listSize; i++) {
logInDetailManager[i] = new HorizontalFieldManager(
Manager.USE_ALL_WIDTH | Field.FOCUSABLE) {
protected void onFocus(int direction) {
super.onFocus(direction);
background_color = Color.RED;
invalidate();
}
protected void onUnfocus() {
invalidate();
background_color = Color.GREEN;
}
And this is how I add my horizontal fields:
logInDetailManager[i].setChangeListener(this);
logInDetailManager[i].add(dummyIcon[i]);
logInDetailManager[i].add(new LabelField("hello"));
logInDetailManager[i].add(new NullField(Field.FOCUSABLE));
add(logInDetailManager[i]);
Sorry, I couldn't comment to my own post yesterday since I'm new to Stackoverflow ;)
Here's how I solved it:
I removed onFocus() and onUnfocus() from the HFM and set the background color in the paint method so the whole row color is changed when focused:
protected void paint(Graphics graphics) {
graphics.setBackgroundColor(isFocus() ? Color.RED : Color.GREEN);
graphics.clear();
invalidate();
super.paint(graphics);
}
I also found out that if you want to set more complex backgrounds (i.e. with a gradient) you can also use the setBackground(int visual, Background background) method:
Background bg_focus = (BackgroundFactory
.createLinearGradientBackground(Color.GREEN, Color.LIGHTGREEN,
Color.LIGHTGREEN, Color.GREEN));
loginDetailManager[i].setBackground(VISUAL_STATE_FOCUS, bg_focus);
Make sure to delete you're paint method when using the setBackground function like that!
I've got a custom (and getting complex) TabControl. It's a gathering of many sources, plus my own wanted features. In it is a custom Panel to show the headers of the TabControl. Its features are to compress the size of the TabItems until they reached their minimum, and then activates scrolling features (in the Panel, again). There is also another custom panel to hold a single button, that renders on the right of the TabItems (it's a "new tab" button).
It all works great, until I try to animate the scrolling.
Here are some relevant snippets :
In the CustomTabPanel (C#, overriding Panel and implementing IScrollInfo):
private readonly TranslateTransform _translateTransform = new TranslateTransform();
public void LineLeft()
{
FirstVisibleIndex++;
var offset = HorizontalOffset + _childRects[0].Width;
if (offset < 0 || _viewPort.Width >= _extent.Width)
offset = 0;
else
{
if (offset + _viewPort.Width > _extent.Width)
offset = _extent.Width - _viewPort.Width;
}
_offset.X = offset;
if (_scrollOwner != null)
_scrollOwner.InvalidateScrollInfo();
//Animate the new offset
var aScrollAnimation = new DoubleAnimation(_translateTransform.X, -offset,
new Duration(this.AnimationTimeSpan), FillBehavior.HoldEnd) { AccelerationRatio = 0.5, DecelerationRatio = 0.5 };
aScrollAnimation.Completed += ScrollAnimationCompleted;
_translateTransform.BeginAnimation(TranslateTransform.XProperty, aScrollAnimation , HandoffBehavior.SnapshotAndReplace);
//End of animation
// These lines are the only ones needed if we remove the animation
//_translateTransform.X = -offset;
//InvalidateMeasure();
}
void ScrollAnimationCompleted(object sender, EventArgs e)
{
InvalidateMeasure();
}
the _translateTransform is initialized in the constructor :
base.RenderTransform = _translateTransform;
Again, everything is fine if I remove the animation part and just replace it with the commented out lines at the end.
I must also point out that the problem is NOT with the animation itself. That part works out well. The problem is about when I remove some tab items : all the layout then screws up. The TranslateTransformation seems to hold on some wrong value, or something.
Thanks in advance.
Well. As it's often the case, I kept working on the thing, and... answered myself.
Could still be useful for other people, so here was the catch. In the line :
var aScrollAnimation = new DoubleAnimation(_translateTransform.X, -offset, new Duration(this.AnimationTimeSpan), FillBehavior.HoldEnd)
{ AccelerationRatio = 0.5, DecelerationRatio = 0.5 };
the FillBehavior should have been FillBehavior.Stop.
As easy as that!
I want to change the direction of my marquee on changeDirection button click.
My code for changing direction is :
private void changeDirection_click(object sender, RoutedEventArgs e)
{
if (_marqueeType == MarqueeType.RightToLeft)
{
_marqueeType = MarqueeType.LeftToRight;
StartMarqueeing(_marqueeType);
}
else if (_marqueeType == MarqueeType.LeftToRight)
{
_marqueeType = MarqueeType.RightToLeft;
StartMarqueeing(_marqueeType);
}
}
And code for start marquee is :
public void StartMarqueeing(MarqueeType marqueeType)
{
double height = canMain.ActualHeight - marqueeList.ActualHeight;
marqueeList.Margin = new Thickness(0, 0, 0, 0);
doubleAnimation.From = -marqueeList.ActualWidth;
doubleAnimation.To = canMain.ActualWidth;
doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(_marqueeTimeInSeconds));
if (marqueeType == MarqueeType.RightToLeft)
{
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Canvas.Right)"));
_storyBoard.Children.Add(doubleAnimation);
_storyBoard.Begin(marqueeList, true);
}
else if (marqueeType == MarqueeType.LeftToRight)
{
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Canvas.Left)"));
_storyBoard.Children.Add(doubleAnimation);
_storyBoard.Begin(marqueeList, true);
}
}
Now here I am able to change the direction from Right to Left only first time.
But when I am change it from Left to Right it’s not changing the marquee position Left to Right.
It looks like you left out a _storyboard = new Storyboard(), perhaps at the top of the StartMarqueeing method.
From what I see it appears that every call to StartMarqueeing will add an additional DoubleAnimation to the storyboard, then start it again. So all the old DoubleAnimations will be recreated, and it looks like they take precedence.
Try creating a new Storyboard object each time, not just re-using it and adding to its children collection.
Update
Oh, now I see the problem. You should not be setting both (Canvas.Left) and (Canvas.Right). Use only one of the two: That's all you need anyway, and using both will give the Canvas conflicting instructions. Traditionally people use (Canvas.Left). I think that's what Canvas selects, which is what is causing your asymmetry.
You may wonder why I say you are using both when you don't think your two animations every run at the same time. Actually they do: The first animation runs then holds the value on the animated property until it is removed or bumped off by another animation. If the second animation then runs and modifies a different property it doesn't bump off the first animation so the first animation's value is still present.
The bottom line is, using (Canvas.Left) on both animations should fix it as long as you are using the default HandoffBehavior.SnapshotAndReplace.