Hello is it possible to create an object that would function like a button?
Because I'm making a room management system for a hotel and the manager wants me to put a graphical representation of the rooms. I'm thinking it would be user friendly if I create an object that would represent the room e.g (rectangle) because I think it's too awful if I put many buttons in it. (it's too painful in the eyes).
The object should be clickable because when the user clicks or double clicks it. The room details would appear.
Thank you very much...
Yes, it is. All of the controls (as long as they inherit from Control, which basically all UI elements do) have a Click-Event, which you can register to so you get notified when it is clicked.
If you tell me if you are using WinForms or WPF I can give you an example of drawing a custom clickabel object.
You can either just set the size of a button to represent the room, or you can catch the Click event of any element you like to use to represent the room, for example a Panel.
You can also create a class that inherits from a control and implements some more features, that way it's easy to reuse it. Example:
public class Room : Panel {
// perhaps something to keep track of what room it is
private int _id;
// a constructor that sets the data that you need
public Room(int id) {
_id = id;
}
protected override OnClick(EventArgs e) {
// here you can handle the click
}
}
You create an object that would inherit from Control, and do custom drawing code using System.Drawing, It's a pretty simple task. With Control you're exposed to regular events like MouseDown, MouseUp, MouseEnter, MouseLeave, OnPaint, PaintBackground. These are events you're going to want if you add effects.
Related
I have been following this guide and have the working example till the very end of the demo (very insightful tutorial, 10/10 would recommend):
https://codenameone.teachable.com/courses/java-for-mobile-devices-introducing-codename-one/lectures/2647773
Now I wanted to expand this to a more practical todo list by adding a Floating Action Button to add new items, like that:
fab = FloatingActionButton.createFAB(FontImage.MATERIAL_ADD);
fab.bindFabToContainer(current.getContentPane(), Component.RIGHT,
Component.BOTTOM);
fab.addActionListener(e -> { // show dialog for adding new item });
This by itself works fine. Now comes the tricky part. When using a long press event on any of the items, two things should happen:
the visual of the long pressed item should change to indicate it is being selected (not in terms of a Checkbox or ToggleButton "select" but a highlight.
the FAB should change its icon and actionlistener to delete the highlighted item.
The long press event is achieved in overriding the longPointPress method from the Checkbox class:
#Override
public void longPointerPress(int x, int y){
mainForm.longPressEvent(this);
// no event parameter for e.consume();
}
To my questions:
Q1: When I use the action listener from the ToggleButton, both the "normal" click event as well as the long Press event are fired. I need to distinguish between the two though.
The longPointerPress method does not have the event in the param list, hence I cannot consume the event after being done with my long Press Event activity. How can I prevent the normal action listener from firing?
Q2: For the "highlight effect", I would like the item to have a margin to all sides, overall shrinking the element by that amount. In other words, without increasing the previous total size. By just adding a margin though, the item gets bigger.
How could a shrink a given element with a margin to all sides, but preserve the original size?
Q3: A FAB only has the option to "setIcon", not "setMaterialIcon". Hence, I am currently recreating the FAB every time it changes, as I dont want to hustle with the involved styles. Is there a better way than this?
//this is the unwanted function, as I dont want to set the style myself
fab.setIcon(FontImage.createMaterial(icon, s));
//Delete FAB pressed, change to Add FAB
fab.remove();
fab = FloatingActionButton.createFAB(FontImage.MATERIAL_ADD);
fab.bindFabToContainer(current.getContentPane(), Component.RIGHT, Component.BOTTOM);
Action event is always invoked on pointer release regardless of whether there was a long press event fired as we don't "know" you processed the longPress event. You would need to create a flag such as:
private boolean handledInLongPress;
public void longPress(int x, int y) {
// do your stuff
handledInLongPress = true;
}
private void handleActionEvent(ActionEvent ev) {
// I'm using this as a placeholder for your event code
// block the event from propagating and undo anything it might
// have triggered
ev.consume();
}
I would recommend using setUIID() on the elements and define a "delete*" set of UIID's. You can define smaller padding and fonts to create the effect of shrinking but that might be tricky if you have icons here as well. You can scale down said icons and keep the original for restoring in a client property.
FAB makes a lot of assumptions so re-creating it (or using two instances) is probably a better approach than trying to set the icon. There is no way to change the icon of the FAB at runtime in the current implementation.
I'm trying to make an augmented reality application with vuforia and unity.
whenever it recognize the image target, it must tell a story by showing text , and it should enable the user to press next and back to go on reading the different parts of this story, I'm totally new to unity and don't know how to handle with UI throughout scripting, I need some help on how to accomplish the part of "going forward and backward on showing the story by hitting Next and Back buttons", and all these parts of story should be related to the same image target in the same scene.
I appreciate it if you help me with an example code.
You should create some script that attach on trackable object, maybe something like this.
public class DataBook {
string[] dataBook;
string idText;
bool isActive;
}
Then you must create another script to set that trackable object is active or not, this link can help you to get that.
https://developer.vuforia.com/forum/faq/unity-how-do-i-get-list-active-trackables
Then after you get the active trackable object, you can set the dialog from the book by create another controller script for button, example
public void Next() {
DataBook[] books = FindObjectsOfType<DataBook>(); // if the object more than one, it will be more easy if it only the one
foreach (var book in books)
{
if (book.isActive) {
book.idText += 1;
textUI.text = book.dataBook[idText]; //textUI assign to object text on canvas
}
}
}
you can learn about unity UI Button on this :
https://unity3d.com/learn/tutorials/modules/beginner/ui/ui-button
Good luck
I have the following problem, and I'd appreciate greatly if someone could help.
I've been trying create a roll-a-ball game in Unity, similar as the one presented in one of the tutorials on their official website, but with one difference: I'd like to add GUI text that would show the score. Every time the ball hits (and destroys) one of the rotating cubes, the score should increase by 1, and the text should show the current score.
I've watched the following tutorial:
http://unity3d.com/learn/tutorials/projects/space-shooter/counting-points
I have created the UI text, called ScoreText, and, on the other hand, I have written the script that makes an instance of GUIText class, called guitext, show the current score. However, I cannot connect my particular GUI text (ScoreText) with the script, i.e. I cannot tell the script to use that particular GUI text to show score. In the video, at 16:35, they just drag the GUI text to the instance of the GUIText class from the script (in my case, guitext), in order to tell the script it's that particular text that should show the score. But when I try to drag it, I simply can't do it. I have no idea why.
I don't know if this could cause the problem: under "Create" in the free version of Unity, I could not find anything called "GUI text" but instead I created a UI text. I know it's the same thing, but... In the script, I define an instance of GUIText class - guitext - so maybe, when I try to add my UI text to it, it won't work because my text really doesn't belong to the GUIText class?
Since you are using Unity 4.6 which has a new GUI system and not the Legacy UI which was present when the tutorial which you mentioned was made. There are two options - either you create an empty gameobject and add add a GUIText component to it. You can add the GUIText to empty gameobject by selecting it in the Hierarchy which should display the objects properties in the Inspector panel.
In the Inspector, you should see an Add Component button, click on it and search for GUIText. Add it and that should solve your problem.
Oh yea, the second option is to migrate to Unity 4.6 new GUI, which should take time unless you are pretty good with unity.
If you want to learn Unity 4.6 GUI, you can refer these links
Unity Official
Unity 4.6 tutorials by TheGameContriver
I am only posting on this because many come to this one and get lost. Here is how to make this work in Unity5.3 at the time of this response.
This is in C#
Simply use the GameController game object to attach the script to. Second create a UI text. Toy only call it score or scoretext for your own referral otherwise the name itself does not matter.
using UnityEngine;
using UnityEngine.UI;///needed to reference the new UI setup in this script type
using System.Collections;/// <summary>
/// allows collections of related information.
/// </summary>
public class GameController : MonoBehaviour {
public GameObject targets;
public Vector3 spawnValues;
public int hazardCount;
public float spawnWait;
public float startWait;
public float waveWait;
public Text Text; /// <summary>
/// change this because you dont actually use the words UI or GUI. Thats just for the reference and not clarified by instructors.
/// </summary>
private int score;
void Start()
{
score = 0;
UpdateScore();
StartCoroutine(SpawnWaves());
}
IEnumerator SpawnWaves()///this depends on the above using System.Collections
{
yield return new WaitForSeconds(startWait);
while (true)
{
for (int i = 0; i < hazardCount; i++)
{
Vector3 spawnPosition = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
Quaternion spawnRotation = Quaternion.identity;
Instantiate(targets, spawnPosition, spawnRotation);
yield return new WaitForSeconds(spawnWait);
}
yield return new WaitForSeconds(waveWait);
}
}
public void AddScore(int newScoreValue)
{
score += newScoreValue;
UpdateScore();
}
void UpdateScore()
{
Text.text = "Score: " + score;
}
}
Confirmed. In the GameController.cs file, change the declaration of public GUIText scoreText to public Text scoreText, and then it will let you drag it on the Game Controller as the video shows.
Update your Unity tutorials, peoples! Just spent an hour trying to figure this out!
One more thing...check the Z position. My UI looked perfect head on in the scene view, but my text never showed in the game...then I rotated the scene view and found my text was way behind the camera. Seems when you add something to the UI, the z value is somewhat random.
WTL/WIN32 newbie here, struggling to understand how messages are passed around.
I'm trying to write an owner-drawn CTabCtrl in WTL. For some (at least to me) incomprehensible reason, WM_DRAWITEM is sent to the parent window, not to the window that actually needs to know. Which makes it difficult to make a nice, self-contained GUI class to simply replace CTabCtrl. I could always capture the message in the parent and pass it on to the tab control, but that would be poor OO design. Is there a way to intercept the message, without requiring extra re-routing code in the owner/parent class?
EDIT: After a bit of googling, I now have
class CQueryTabCtrl :
public CWindowImpl<CQueryTabCtrl, CTabCtrl>,
public COwnerDraw<CQueryTabCtrl>
{
public:
DECLARE_WND_SUPERCLASS(NULL, CTabCtrl::GetWndClassName())
BEGIN_MSG_MAP(CQueryTabCtrl)
CHAIN_MSG_MAP(COwnerDraw<CQueryTabCtrl>)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
BOOL PreTranslateMessage(MSG* pMsg)
{
pMsg;
return FALSE;
}
void DeleteItem(LPDELETEITEMSTRUCT /*lpDeleteItemStruct*/)
{
}
void DrawItem ( LPDRAWITEMSTRUCT lpdis )
{
CDCHandle dc = lpdis->hDC;
CDC dcMem;
dcMem.CreateCompatibleDC ( dc );
dc.SaveDC();
dcMem.SaveDC();
dc.FillSolidRect ( &lpdis->rcItem, RGB(255,0,0) );
dcMem.RestoreDC(-1);
dc.RestoreDC(-1);
}
};
Which is obviously utterly wrong, since DrawItem() is never called.
WM_DRAWITEM is sent to parent by design.
Sent to the parent window of an owner-drawn button, combo box, list box, or menu when a visual aspect of the button, combo box, list box, or menu has changed.
You handle it on hosting window, and with WTL you might leverage COwnerDraw class on it and/or reflect messages there so that they are sent back to the window where your subclassing WindowProc would handle them as you perhaps originally planned.
This answer is a bit late to the party, but might help others...
There's no way to directly achieve reflected messages w/o extra routing code, because that's how Window's window messaging works, as Roman points out.
ATL however has mechanisms to reflect messages onto child windows, which at least helps in keeping self-written code to a minimum.
1) Opt-In to reflection
This requires an extra step in your parent window, in order to tell it to reflect messages from child windows onto them, using the REFLECT_NOTIFICATIONS() macro:
// Just a made-up dialog class for outlining message reflection installed on the parent window
class SomeDialog : public CDialogImpl<SomeDialog, CWindow>
{
public:
BEGIN_MSG_MAP_EX(SomeDialog)
REFLECT_NOTIFICATIONS()
END_MSG_MAP()
};
2) Handle reflected (owner-draw) messages
Because your control will receive reflected messages, and the COwnerDraw mixin provides an alternative message map for those, you simply chain to that message map, using the CHAIN_MSG_MAP_ALT() macro.
class CQueryTabCtrl :
public CWindowImpl<CQueryTabCtrl, CTabCtrl>,
public COwnerDraw<CQueryTabCtrl>
{
public:
DECLARE_WND_SUPERCLASS(NULL, CTabCtrl::GetWndClassName())
BEGIN_MSG_MAP(CQueryTabCtrl)
CHAIN_MSG_MAP_ALT(COwnerDraw<CQueryTabCtrl>, 1)
END_MSG_MAP()
void DrawItem(LPDRAWITEMSTRUCT)
{
// ...
}
};
Also see a complete owner-drawn tablist control from the wtlext repository, which can serve as an example (Dislaimer: I am associated with the author FireDaemon Technologies Ltd).
I Am currently working on an open source Game engine in C for people to learn from etc and i was wondering what would be the best way to do the input for The UI system via mouse clicks, key press's etc.
Currently i have the the ui system's input using function pointers where to set a function the user would just go.
button1.mousepress = button1_press;
then if the user clicked button1 it would loop through to find button 1 then do button1's click event. however i need it to go to a event inside of the control then to the users control. The way i have the function pointers setup is as follows.
struct widget
{
//contains control special data
void *control;
//contains the parent of the widget.
widget *parent;
//contains events for quick calling
void(*draw)(widget *);
void(*mousepress)(widget *,int,int);
void(*mouserelease)(widget *,int,int);
void(*mousewheel)(widget *,int);
void(*keypressed)(widget *,int,int);
//hidden and shown arrays
widget_array shown;
widget_array hidden;
vector2ui pos;
vector2ui actualpos;
vector2ui originalpos;
vector2i imgpos;
image img;
uint16 width;
uint16 height;
uint8 type;
sbool action;
};
As you can see the function pointers are not generic at the moment, so if i have to make them generic i will. other than that what would be the best way to set the function pointers up to allow them to go into the gui controls Event then go to the user made
button1.mousepress. Any ideas on what the best method for doing thins would be. A friend of mine suggested Chaining but i could not figure out how chaining works....
Thank you for any of you who read through this, as well as thank you to those whom will help.