如何为计算器实现两个文本框的使用?

时间:2018-10-24 18:32:10

标签: vb.net

我的任务是创建一个使用来自两个文本框的数字输入的计算器。该计算器仅在处理单个文本框(boxequation1)时起作用,但我需要它接受来自另一个文本框(boxequation2)的另一个输入。有什么方法可以将数字输入到boxequation1中,选择一个运算,将数字输入到boxquation2中,然后计算结果?

    Public Class Form1
Private Sub ButtonClickMethod(sender As Object, e As EventArgs) Handles num0.Click, num1.Click, num2.Click, num3.Click, num4.Click, num5.Click, num6.Click, num7.Click, num8.Click, num9.Click, opdivision.Click, opmultiply.Click, opdecimal.Click, opclear.Click, opminus.Click, opadd.Click, opequal.Click
    Dim button As Button = CType(sender, Button)
    If button.Name = "num1" Then
        boxequation1.Text = boxequation1.Text + "1"
    End If
    If button.Name = "num2" Then
        boxequation1.Text = boxequation1.Text + "2"
    End If
    If button.Name = "num3" Then
        boxequation1.Text = boxequation1.Text + "3"
    End If
    If button.Name = "num4" Then
        boxequation1.Text = boxequation1.Text + "4"
    End If
    If button.Name = "num5" Then
        boxequation1.Text = boxequation1.Text + "5"
    End If
    If button.Name = "num6" Then
        boxequation1.Text = boxequation1.Text + "6"
    End If
    If button.Name = "num7" Then
        boxequation1.Text = boxequation1.Text + "7"
    End If
    If button.Name = "num8" Then
        boxequation1.Text = boxequation1.Text + "8"
    End If
    If button.Name = "num9" Then
        boxequation1.Text = boxequation1.Text + "9"
    End If
    If button.Name = "num0" Then
        boxequation1.Text = boxequation1.Text + "0"
    End If
    If button.Name = "opdecimal" Then
        boxequation1.Text = boxequation1.Text + "."
    End If
    If button.Name = "opequal" Then
        Dim equation1 As String = boxequation1.Text
        Dim equation2 As String = boxequation2.Text
        Dim result = New DataTable().Compute(equation1, Nothing)

        boxresult.Text = result
    End If
    If button.Name = "opminus" Then
        boxequation1.Text = boxequation1.Text + "-"
        boxoperator.Text = boxoperator.Text + "-"
    End If
    If button.Name = "opmultiply" Then
        boxequation1.Text = boxequation1.Text + "*"
        boxoperator.Text = boxoperator.Text + "x"
    End If
    If button.Name = "opdivision" Then
        boxequation1.Text = boxequation1.Text + "/"
        boxoperator.Text = boxoperator.Text + "÷"
    End If
    If button.Name = "opadd" Then
        boxequation1.Text = boxequation1.Text + "+"
        boxoperator.Text = boxoperator.Text + "+"
    End If
    If button.Name = "opclear" Then
        boxequation1.Clear()
        boxoperator.Clear()
        boxresult.Clear()
    End If
End Sub
Private Sub opbackspace_Click(sender As Object, e As EventArgs) Handles opbackspace.Click
    boxequation1.Text = boxequation1.Text.Remove(boxequation1.Text.Count - 1)
End Sub

End Class

1 个答案:

答案 0 :(得分:0)

我很喜欢你的作业。

现在...我不确定应该如何帮助您。我最初想对它进行编码并混淆部分代码,以便您可以检查清楚什么并自己理解其余内容,但是另一方面,我不知道这是否真的有用。我想也许您会提供更多解释,更好。

因此,我根据您之前发布的内容重新编码了整个内容。 我对我的工作进行了认真的评论,这样您就可以理解为什么我做了那场战争,但实际上您可以并且应该问我一些问题,这些问题在这里并不是很清楚。 而且,一旦您对此感到更有信心,就应该取消我的工作并重新编码,但这一次是从头开始。毕竟,您这样做是为了学习!

这是什么样子:

.-...-.-.-.-.-.-。enter image description here

这是一个非常自定义的New()Sub。这不是我编码的方式。我只需要此模棱两可的前三行,但我希望您看到其余内容,因为这是我在设计器中设置控件的方式。 您确实应该在设计器中设置控件名称,文本和标签。 这部分的确存在,只是因为这样更容易向您显示这些设置

Private Sub New()
    InitializeComponent()

    _currentTextBox = Number1TextBox
    _locked = False
    ResultsTextBox.TextAlign = HorizontalAlignment.Center
    ResultsTextBox.Text = "SUPER DUPER CALCULATOR"
    For Each textBox As System.Windows.Forms.TextBox In {ResultsTextBox, Number1TextBox, Number2TextBox}
        'This prevent the user from writing in your textboxes instead of using the buttons.
        textBox.ReadOnly = True
    Next

    'I used the .Text and .Tag properties to make the code easier to manage. Observe:
    num0Button.Text = "0"
    num1Button.Text = "1"
    num2Button.Text = "2"
    num3Button.Text = "3"
    '...
    num9Button.Text = "9"
    opAddButton.Text = "+"
    opMinusButton.Text = "-"
    opMultiplyButton.Text = "x"
    opDivideButton.Text = "÷"
    For Each button As Button In {num1Button, num2Button, num3Button, num4Button, num5Button, num6Button, num7Button, num8Button, num9Button}
        button.Tag = "number"
    Next
    For Each button As Button In {opAddButton, opMinusButton, opMultiplyButton, opDivideButton}
        button.Tag = "operation"
    Next
    num0Button.Tag = "numberZero"
    opDecimalButton.Tag = "decimal"
    opBackspaceButton.Tag = "backspace"
    opEqualButton.Tag = "equal"
End Sub

现在是真正的代码:班级将需要和使用的潜艇:

'Class variables are useful to remember informations which will be useful at several unrelated places.
'_currentTextBox is a pointer to the TextBox which is currently being filled
Private _currentTextBox As System.Windows.Forms.TextBox = Number1TextBox
'_Llocked will prevent the user from messing with the calculator after he pressed "equal"
Private _locked As Boolean = False

'I didn't like this idea but I went with it since it was your initial method.
'Notice how shoter this iteration of your idea is. Strive to shorten your code while making your variable names much easier to read.
'For real, make sure your variables are aptly names. Every control should be identified as such (the button num0 should be names num0Button for example)
'Code is hard enough to read without making it sibylline
Private Sub ButtonClickMethod(sender As Object, e As EventArgs) Handles num0Button.Click, num1Button.Click, num2Button.Click, num3Button.Click, num4Button.Click, num5Button.Click, num6Button.Click, num7Button.Click, num8Button.Click, num9Button.Click, opDivideButton.Click, opMultiplyButton.Click, opDecimalButton.Click, opClearButton.Click, opMinusButton.Click, opAddButton.Click, opEqualButton.Click, opBackspaceButton.Click
    'DirectCast is more strick than CType. For this operation, it doesn't really make a difference, but that's the one you want anyway.
    Dim button As System.Windows.Forms.Button = DirectCast(sender, System.Windows.Forms.Button)

    'The boolean _locked prevent the user from messing with your beautiful calculator.
    If Not _locked Then
        'This is where the .Tag property save lifes. All numbers (but zero) are "number" now. BAM!
        Select Case button.Tag.ToString
            Case "number"
                _currentTextBox.Text += button.Text
            Case "numberZero"
                'You don't want your clever teacher to try to divide by zero, or create a number with 5 zeros before the actual number.
                'This is how you can do this.
                If _currentTextBox.Text.Length > 0 Then
                    _currentTextBox.Text += button.Text
                End If
            Case "decimal"
                If _currentTextBox.Text.Length > 0 AndAlso Not _currentTextBox.Text.Contains(".") Then
                    _currentTextBox.Text += button.Text
                End If
            Case "operation"
                ResetOperationTextBoxes()
                'here's a nifty visual cue about which operation has been selected. It's not really important.
                button.BackColor = Color.LightSalmon
                'This label will be used to Calculate() the operation. It's important!
                OpLabel.Text = button.Text
            Case "backspace"
                If _currentTextBox.Text.Length > 0 Then
                    _currentTextBox.Text = _currentTextBox.Text.Substring(0, _currentTextBox.Text.Length - 1)
                End If
            Case "equal"
                'I could have put the code here instead of making another sub, but I didn't.
                'There are two valid reasons for this.
                '1- This code might be useful on it's own later: maybe something else will Calculate() or LockCalculator or ResetCalculator later.
                '2- try to avoid blobs of code. A big and complex sub is easier to understand when it's divided between several clean and clear smaller subs.
                '   (of course, you cannot always subdivise Subs. Use common sense)
                Calculate()
        End Select
    End If

    'This check is all alone because I want it to work even if the calculator is locked.
    If button.Tag.ToString = "clear" Then
        ResetCalculator()
    End If
End Sub

Private Sub Calculate()
    'Always make checks to make sure that things are going the way you think they should be going.
    'for example, here I want to have 2 numbers and an operation, er else I'll just ignore this click.
    If Number1TextBox.Text.Length > 0 AndAlso Number2TextBox.Text.Length > 0 And OpLabel.Text <> "?" Then
        'If the user could mess with the textboxes, i would have to make further checks to avoid crashes, but I already force the user to use only numbers se we're cool.
        Dim number1 As Double = Convert.ToDouble(Number1TextBox.Text)
        Dim number2 As Double = Convert.ToDouble(Number2TextBox.Text)
        Dim result As Double

        Select Case OpLabel.Text
            Case "+"
                result = number1 + number2
            Case "-"
                result = number1 - number2
            Case "x"
                result = number1 * number2
            Case "÷"
                result = number1 / number2
        End Select

        ResultsTextBox.TextAlign = HorizontalAlignment.Right
        ResultsTextBox.Text = result.ToString
        LockCalculator(True)
    End If
End Sub

'By using a boolean to signify to this Sub if I want to lock or unlock things, I make it easier to automatize this operation (and I have only one Sub instead of two).
Private Sub LockCalculator(ByVal isLocked As Boolean)
    _locked = isLocked
    'I'm kinda cheating here: I put the calculator inside a GroupBox just so I could be lazier and do this.
    'Being lazy is great for a coder, as long as you think ahead (and avoid being a nuisance to yourself when you'll come back to this code and weep).
    For Each control As System.Windows.Forms.Control In CalculatorGroupBox.Controls
        control.Enabled = Not isLocked
    Next
    'Except that I want this button to always be available, so I enable it. This operation wouldn't be necessary if isLocked is True, but checking for that is longer than just doing it.
    opClearButton.Enabled = True
End Sub

Private Sub ResetCalculator()
    ResetNumberTextBoxes()
    ResetOperationTextBoxes()
    LockCalculator(False)
    _currentTextBox = Number1TextBox
End Sub

Private Sub ResetNumberTextBoxes()
    For Each textBox As System.Windows.Forms.TextBox In {Number1TextBox, Number2TextBox}
        textBox.Text = ""
    Next
    'Mea Culpa: I shouldn't had done a For Each for 2 elements like that. I did it anyway. Please don't call the Fun Police on me.
    'Also, you can now guess that using For Each loops to set up controls is a work method I like. Some don't like that.
    'There is about as many ways to code something as there are coders. You have to find your own, sure, but then you'll get hired somewhere
    'and they will absolutely hate everything that you do that isn't done the way they like it. And they will be right. On a big project where
    'several coders works, at the same time and for month and years, you have to find a common ground or else the code will become a nightmare
    'to understand and maintain. Trust me: being able to adapt quickly to other's work methodology is a GREAT skill in this field of work.

    ResultsTextBox.TextAlign = HorizontalAlignment.Center
    ResultsTextBox.Text = "SUPER DUPER CALCULATOR"
End Sub

Private Sub ResetOperationTextBoxes()
    For Each button As System.Windows.Forms.Button In {opAddButton, opMinusButton, opMultiplyButton, opDivideButton}
        button.BackColor = DefaultBackColor
    Next
    OpLabel.Text = "?"
End Sub

'This sub is great. It uses the _currentTextBox as a pointer. Maybe you're not familiar with pointers, I don't know. The short explanation is this:
'A pointer is like a phone number. You can give your number to several people without "losing" it. And if they call you and tell you something, they
'are all speaking to the same person.
'_currentTextBox is a pointer which can point toward Number1TextBox or Number2TextBox.
'This Event makes it so when the user click on Number1TextBox or Number2TextBox, the pointer updates it's "phone number" to the right box,
'so later when we'll write we'll write in the last one which was clicked on.
Private Sub NumberTextBoxes_Click(sender As Object, e As EventArgs) Handles Number1TextBox.Click, Number2TextBox.Click
    _currentTextBox = DirectCast(sender, System.Windows.Forms.TextBox)
End Sub

您在这里。希望您能像我一样享受编码的乐趣!

在我现在睡觉之前,我认为您应该努力改善以下几点:

1 用非常明显的名称命名控件。没人在乎名字长,反正我们都使用intelliSense。但是,我们无法一目了然的事情还不够清楚!

2 与您的变量相同。实际上,所有具有名称的东西都一样。如果您向队友展示您的工作,而他却无法仅凭其名字就猜出您正在谈论哪个控件,那还不够清楚!

3 您将通过了解朋友,计算机而不断学习剩余的知识。

4 您应该打开“显式”和“严格”模式。它可以帮助您了解正在使用的类型以及它们如何交互。它将大大减少可怕操作的风险。实际上,似乎编码人员的经验越丰富,他对这些选项的需求就越少,编码人员的经验越丰富,他越有可能在其所有工作的开始就拥有这两行代码...

这是我在家中开始每一页VB代码的方式:

.-...-.-.-.-.-.-。Creation date, Author, etc.

4 提出问题!对我,对同学,对老师!询问一切进展情况!

祝你好运!