I have a set of codes in my function with a lot of if-else loops but each doing a diffrent one
like
if(ddlname.SelectedIndex = 0)
{
//do this
}
else
{
//do this
}
if (txtprice.Text ="")
{
//do tis
}
else
{
//do this
}
my whole program looks clumsy and unnecessarily long because of this one. I have some 20 dropdownlists and ten textboxes. Is there way to make this as simple as 1 or 2 for loops ?
I am currently reading Clean Code by Robert C. Martin. According to his book, you should refactor your method into several smaller methods, doing exactly one thing. You should for example extract every do this into its own method.
As to your question, I don't think there is any way of achieving the same logic using for loops, unless you do the same for every call.
foreach (ctl in page.ctls)
{
TextBox tempTextBox = ctl as TextBox;
if (tempTextBox != null)
{
doTheSameForEveryTextBox(tempTextBox)
}
DropDownList tempDropDownList as DropDownList; // not sure if this is the right Type...
if (tempDropDownList != null)
{
doTheSameForEveryTextBox(tempDropDownList)
}
}
void doTheSameForEveryTextBox(TextBox tempTextBox)
{
if (tempTextBox.Text == "")
{
//TODO: implement your code here
}
}
void doTheSameForEveryDropDownList(DropDownList tempDropDownList)
{
if (tempDropDownList.SelectedIndex == 0)
{
//TODO: implement your code here
}
}
Related
I have a few keys that can be pressed, and each key press emits a signal that corresponds to it. However, the key presses do different things depending on which object is being operated on. I have an example illustration below.
// keyboard.cpp
void receive_key_press(uint8_t key_id){
if(key_id == 1)
emit key_one_pressed();
else if(key_id == 2)
emit key_two_pressed();
else if(key_id == 3)
emit key_three_pressed();
}
Class A : public QObject {
// use Q_PROPERTY here to expose the member var 'model' to qml
public:
int model;
}
int main(){
Keyboard keyboard;
A obj;
if (some_condition)
obj.model = 5;
else
obj.model = 7;
// Engine initialization here and exposing 'obj' and 'keyboard' to qml using setContextProperty
}
Then in main.qml
Connections {
target: keyboard
onKey_one_pressed: {
if (obj.model == 5)
// do something
else
// do something else
// execute some common code here
}
onKey_two_pressed: {
if (obj.model == 5)
// do something
else
// do something else
}
onKey_three_pressed: {
if (obj.model == 5)
// do something
else
// do something else
}
}
How can I simplify and avoid all those if-else conditions in the main.qml. Is there something in Qt that can make this easier, and provide some global way of handling a 'Gui state'. I know there's like a File Selector in Qt but that's not really what I'm going for. I want to have a better approach instead of having if-else everywhere in the Gui for different model.
Thanks in advance
In your particular example, factor it out into a common function:
Connections {
target: keyboard
function commonCode() {
// execute some common code here
}
onKey_one_pressed: {
if (obj.model == 5)
// do something
else
// do something else
commonCode();
}
onKey_two_pressed: {
if (obj.model == 5)
// do something
else
// do something else
commonCode();
}
onKey_three_pressed: {
if (obj.model == 5)
// do something
else
// do something else
commonCode();
}
}
You can also put commonCode in a more broadly accessible place to further reduce code duplication.
However, there is also QML States: https://doc.qt.io/qt-5/qtquick-statesanimations-states.html
This is a very handy way to manage different configurations of your GUI. You can use PropertyChanges with it to override the signal handler of objects based on your model value.
I am trying to make a program where you are allowed to select between an option of shapes, and then drawing it. To allow for multiple shapes I created a vector of a class which creates shapes (Shapes are set up with the chosen function). My problem is the mouse click is too long, so it assigns it to everything in the vector, so you can't create a new shape. Is there a problem in my logic, or is there a problem in the code?
Here is my attempt:
for (auto& it : onCanvas) {
if (Mouse::isButtonPressed(Mouse::Left)) {
if (mousepointer.getGlobalBounds().intersects(circleOption.getGlobalBounds())) {
it.chosen(circles);
}
if (mousepointer.getGlobalBounds().intersects(rectOption.getGlobalBounds())) {
it.chosen(rectangle);
}
if (mousepointer.getGlobalBounds().intersects(triOption.getGlobalBounds())) {
it.chosen(triangles);
}
if (mousepointer.getGlobalBounds().intersects(it.shape.getGlobalBounds()) || it.dragging) {
it.shape.setPosition(mousepointer.getPosition());
it.dragging = true;
}
}
if (!Mouse::isButtonPressed) {
it.dragging = false;
}
win.draw(it.shape);
}
Your source-code is a bit incomplete (what is onCanvas and mousepointer). But I guess the problem is that this snippet is called multiple times while your mouse is clicked. To avoid that you can do two thing.
In the first solution you use events, so you only add shapes when the state of the mousebutton changes (you can additionally listen to the MouseButtonReleased to simulate a full click):
if (event.type == sf::Event::MouseButtonPressed)
{
if (event.mouseButton.button == sf::Mouse::Left)
{
// Hit Detection
}
}
or second solution you remember the last state of the button (probably do the mouse check once outside of the for loop):
bool mouse_was_up = true;
if (mouse_was_up && Mouse::isButtonPressed(Mouse::Left)) {
mouse_was_up = false;
for (auto& it : onCanvas) {
// Hit Detection
}
}
else if (!Mouse::isButtonPressed(Mouse::Left))
mouse_was_up = true;
I would rather stick to the first solution because when your click is too short and your gameloop is in another part of the game logic, you can miss the click.
Alright so here is my code. This should be really simple but it doesn't want to work with me for some reason. Raycast sends a ray from the mouse, if it hits an object with a tag, it assigns a number to a variable. If it doesn't hit an object, then it sets the variable as -99. For some reason mine is hanging on:
A. I don't hit the objects, it outputs -99 the first time but after that it hangs on getting assigned 4.
B.I hit the objects and it will work just fine. After I click OFF the objects it hangs on the variable from the object I just hit previously.
em.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameFunctions : MonoBehaviour {
int Hitnum = -99;
void Start () {
}
void Update () {
if (Input.GetMouseButtonDown (0)) {
objectCheck ();
}
}
//end of UPDATE function
public void objectCheck () {
RaycastHit hit;
Ray ray = camera.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, out hit, 10000.0f)) {
if (hit.collider.tag == "Box") {
Hitnum = 1;
} else if (hit.collider.tag == "Sphere") {
Hitnum = 2;
} else if (hit.collider.tag == "Pyramid") {
Hitnum = 3;
} else if (hit.collider.tag == "Trapezoid") {
Hitnum = 4;
} else {
Hitnum = -99;
}
}
Debug.Log (Hitnum);
}
//end of check
}
Thanks in advance. This is driving me nuts because it should be simple.
EDIT: posted full code this time, yes all of it. I should mention that there are no other objects with tags, it's just null space. This was supposed to be a very basic shape identifier for kids.
EDIT:EDIT: I expect it to put out -99 if you do not hit the object. Later I will probably do something with the numbers but right now I jest need to fix this.
Restarted unity, everything works fine now. Thanks. Looked through my settings to see what had changed. I earlier deleted the background that had a background tag on it. I guess unity decided that if there is not hit on raycast, it will get the object that it last hit?
I am trying to make my basic loading screen transition over to game level screen. So what i wanted to do is, once the loading screen is active (or has appeared onscreen), I want at this point to start loading my game state. What it is doing at the moment is loading everything at the start, and this does take a while.
So currently my project starts off with a main menu. Then when i press enter, its starts the loading screen. I have my manual state change using keypresses like so:
void Game::update()
{
static bool enterPreviouslyPressed = false;
static bool escapePreviousPressed = false;
const Uint8 *keys = SDL_GetKeyboardState(NULL);
if (keys[::SDL_SCANCODE_ESCAPE] && !escapePreviousPressed && typeid(*fsm->getState()) == typeid(GameState))
{
fsm->setState(menuState);
}
else if (keys[::SDL_SCANCODE_RETURN] && !enterPreviouslyPressed && typeid(*fsm->getState()) == typeid(MainMenuState))
{
fsm->setState(loadingState);
}
else if ((keys[::SDL_SCANCODE_RETURN] && !enterPreviouslyPressed) && typeid(*fsm->getState()) == typeid(LoadScreenState))
{
fsm->setState(gameState);
}
else if (keys[::SDL_SCANCODE_ESCAPE] && !escapePreviousPressed && typeid(*fsm->getState()) == typeid(MainMenuState))
{
exit(0);
}
enterPreviouslyPressed = keys[::SDL_SCANCODE_RETURN] != 0;
escapePreviousPressed = keys[::SDL_SCANCODE_ESCAPE] != 0;
fsm->update();
}
I did this to initially does this so i could change states manually to check that everything works. I was wondering if there was an easy(ish) way, like boolean flags for example or another simpler way to do this. I wasn't able find any tutorials online so wondering if someone knows the best solution as to how to do this. I did see a question on here, kindda similar but I wasn't sure if it answered my question as the person did this in threads which I am not familiar with how to implement. Apologies if I dont seem to have the logic correct - so please advise otherwise.
Looks fairly standard, except I would simplify it by keeping two keyboard state variables declared as class variables, like:
const Uint8 *curKeys = SDL_GetKeyboardState(NULL), *prevKeys;
// ...
void Game::update() {
prevKeys = curKeys;
curKeys = = SDL_GetKeyboardState(NULL);
//and so then compare curKeys to prevkeys
//and ditch the booleans
// ...
}
How to properlly use setUpdatesEnabled to help GUI performance?
Here is my code:
void uavTabGroup::updateMgr()
{
setUpdatesEnabled(false);
for (updateCtr = 0; updateCtr < max_num; updateCtr++)
{
if (infoView[updateCtr] != NULL)// its a child widget to the current widget
{
infoView[updateCtr]->updateDisplay();
}
}
setUpdatesEnabled(true);
}
However, there is no improvement compared to don't use setUpdatesEnalbed() function, am I doing this wrong. BTW, all the infoView[i] are in a girdlayout of the current widget.
Now I am doing the updating in this way:
void uavTabGroup::updateMgr()
{
if (updateCtr >= max_num)
updateCtr = 0;
if (infoView[updateCtr] != NULL)
{
infoView[updateCtr]->updateDisplay();
}
updateCtr++;
}
And trigger the updateMgr at a higher frequency, and the child widgets are getting updated one by one sequentially.
But someone told me this is wrong... So which is the correct solution?